mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	alembic: Allow cdr, config and voicemail to exist in the same schema
cdr, config and voicemail are all separate alembic trees. Because alembic's default is to use a table named 'alembic_version' to store the current tree revision, the 3 trees can't exist in the same schema without stepping on each other. Now each tree uses 'alembic_version_<tree_name>' as the version table. Each tree's env.py script now first checks for 'alembic_version'. If it finds it AND its revision is in the tree's history, the script renames it to 'alembic_version_<tree_name>'. Regardless, the script then continues with the migration using 'alembic_version_<tree_name>' and creates that table if it's not found. The result is that if an existing 'alembic_version' table was found but it didn't belong to this tree, it's left alone and 'alembic_version_<tree_name>' is used or created. WARNING: If multiple trees are using the same schema, they MUST NOT CRU or D any objects with names that might exist in the other trees. An example would be 'yesno_values' type. If two trees perform operations on it, one tree could pull it out from under the other. Thankfully we currently don't share any names among cdr, config and voicemail. NOTE: Since the env.py scripts in each tree were identical, a common env.py has been placed in the ast-db-manage directory and a symlink to it has been placed in each tree directory. ASTERISK-24311 #close Reported-by: Dafi Ni Change-Id: I4d593f000350deb5d21a14fa1e9bc3896844d898
This commit is contained in:
		| @@ -1,74 +0,0 @@ | ||||
| from __future__ import with_statement | ||||
| from alembic import context | ||||
| from sqlalchemy import engine_from_config, pool | ||||
| from logging.config import fileConfig | ||||
|  | ||||
| # this is the Alembic Config object, which provides | ||||
| # access to the values within the .ini file in use. | ||||
| config = context.config | ||||
|  | ||||
| # Interpret the config file for Python logging. | ||||
| # This line sets up loggers basically. | ||||
| try: | ||||
|     fileConfig(config.config_file_name) | ||||
| except: | ||||
|     pass | ||||
|  | ||||
| # add your model's MetaData object here | ||||
| # for 'autogenerate' support | ||||
| # from myapp import mymodel | ||||
| # target_metadata = mymodel.Base.metadata | ||||
| target_metadata = None | ||||
|  | ||||
| # other values from the config, defined by the needs of env.py, | ||||
| # can be acquired: | ||||
| # my_important_option = config.get_main_option("my_important_option") | ||||
| # ... etc. | ||||
|  | ||||
| def run_migrations_offline(): | ||||
|     """Run migrations in 'offline' mode. | ||||
|  | ||||
|     This configures the context with just a URL | ||||
|     and not an Engine, though an Engine is acceptable | ||||
|     here as well.  By skipping the Engine creation | ||||
|     we don't even need a DBAPI to be available. | ||||
|  | ||||
|     Calls to context.execute() here emit the given string to the | ||||
|     script output. | ||||
|  | ||||
|     """ | ||||
|     url = config.get_main_option("sqlalchemy.url") | ||||
|     context.configure(url=url) | ||||
|  | ||||
|     with context.begin_transaction(): | ||||
|         context.run_migrations() | ||||
|  | ||||
| def run_migrations_online(): | ||||
|     """Run migrations in 'online' mode. | ||||
|  | ||||
|     In this scenario we need to create an Engine | ||||
|     and associate a connection with the context. | ||||
|  | ||||
|     """ | ||||
|     engine = engine_from_config( | ||||
|                 config.get_section(config.config_ini_section), | ||||
|                 prefix='sqlalchemy.', | ||||
|                 poolclass=pool.NullPool) | ||||
|  | ||||
|     connection = engine.connect() | ||||
|     context.configure( | ||||
|                 connection=connection, | ||||
|                 target_metadata=target_metadata | ||||
|                 ) | ||||
|  | ||||
|     try: | ||||
|         with context.begin_transaction(): | ||||
|             context.run_migrations() | ||||
|     finally: | ||||
|         connection.close() | ||||
|  | ||||
| if context.is_offline_mode(): | ||||
|     run_migrations_offline() | ||||
| else: | ||||
|     run_migrations_online() | ||||
|  | ||||
							
								
								
									
										1
									
								
								contrib/ast-db-manage/cdr/env.py
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								contrib/ast-db-manage/cdr/env.py
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | ||||
| ../env.py | ||||
| @@ -1,74 +0,0 @@ | ||||
| from __future__ import with_statement | ||||
| from alembic import context | ||||
| from sqlalchemy import engine_from_config, pool | ||||
| from logging.config import fileConfig | ||||
|  | ||||
| # this is the Alembic Config object, which provides | ||||
| # access to the values within the .ini file in use. | ||||
| config = context.config | ||||
|  | ||||
| # Interpret the config file for Python logging. | ||||
| # This line sets up loggers basically. | ||||
| try: | ||||
|     fileConfig(config.config_file_name) | ||||
| except: | ||||
|     pass | ||||
|  | ||||
| # add your model's MetaData object here | ||||
| # for 'autogenerate' support | ||||
| # from myapp import mymodel | ||||
| # target_metadata = mymodel.Base.metadata | ||||
| target_metadata = None | ||||
|  | ||||
| # other values from the config, defined by the needs of env.py, | ||||
| # can be acquired: | ||||
| # my_important_option = config.get_main_option("my_important_option") | ||||
| # ... etc. | ||||
|  | ||||
| def run_migrations_offline(): | ||||
|     """Run migrations in 'offline' mode. | ||||
|  | ||||
|     This configures the context with just a URL | ||||
|     and not an Engine, though an Engine is acceptable | ||||
|     here as well.  By skipping the Engine creation | ||||
|     we don't even need a DBAPI to be available. | ||||
|  | ||||
|     Calls to context.execute() here emit the given string to the | ||||
|     script output. | ||||
|  | ||||
|     """ | ||||
|     url = config.get_main_option("sqlalchemy.url") | ||||
|     context.configure(url=url) | ||||
|  | ||||
|     with context.begin_transaction(): | ||||
|         context.run_migrations() | ||||
|  | ||||
| def run_migrations_online(): | ||||
|     """Run migrations in 'online' mode. | ||||
|  | ||||
|     In this scenario we need to create an Engine | ||||
|     and associate a connection with the context. | ||||
|  | ||||
|     """ | ||||
|     engine = engine_from_config( | ||||
|                 config.get_section(config.config_ini_section), | ||||
|                 prefix='sqlalchemy.', | ||||
|                 poolclass=pool.NullPool) | ||||
|  | ||||
|     connection = engine.connect() | ||||
|     context.configure( | ||||
|                 connection=connection, | ||||
|                 target_metadata=target_metadata | ||||
|                 ) | ||||
|  | ||||
|     try: | ||||
|         with context.begin_transaction(): | ||||
|             context.run_migrations() | ||||
|     finally: | ||||
|         connection.close() | ||||
|  | ||||
| if context.is_offline_mode(): | ||||
|     run_migrations_offline() | ||||
| else: | ||||
|     run_migrations_online() | ||||
|  | ||||
							
								
								
									
										1
									
								
								contrib/ast-db-manage/config/env.py
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								contrib/ast-db-manage/config/env.py
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | ||||
| ../env.py | ||||
							
								
								
									
										140
									
								
								contrib/ast-db-manage/env.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										140
									
								
								contrib/ast-db-manage/env.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| from __future__ import with_statement | ||||
| from alembic import context | ||||
| from alembic.script import ScriptDirectory | ||||
| from alembic.operations import Operations | ||||
| from sqlalchemy import engine_from_config, pool | ||||
| from logging.config import fileConfig | ||||
| import logging | ||||
|  | ||||
| # this is the Alembic Config object, which provides | ||||
| # access to the values within the .ini file in use. | ||||
| config = context.config | ||||
|  | ||||
| # Interpret the config file for Python logging. | ||||
| # This line sets up loggers basically. | ||||
| try: | ||||
|     fileConfig(config.config_file_name) | ||||
| except: | ||||
|     pass | ||||
|  | ||||
| logger = logging.getLogger('alembic.runtime.setup') | ||||
| # add your model's MetaData object here | ||||
| # for 'autogenerate' support | ||||
| # from myapp import mymodel | ||||
| # target_metadata = mymodel.Base.metadata | ||||
| target_metadata = None | ||||
|  | ||||
| # other values from the config, defined by the needs of env.py, | ||||
| # can be acquired: | ||||
| # my_important_option = config.get_main_option("my_important_option") | ||||
| # ... etc. | ||||
|  | ||||
| def run_migrations_offline(): | ||||
|     """Run migrations in 'offline' mode. | ||||
|  | ||||
|     This configures the context with just a URL | ||||
|     and not an Engine, though an Engine is acceptable | ||||
|     here as well.  By skipping the Engine creation | ||||
|     we don't even need a DBAPI to be available. | ||||
|  | ||||
|     Calls to context.execute() here emit the given string to the | ||||
|     script output. | ||||
|  | ||||
|     """ | ||||
|     url = config.get_main_option("sqlalchemy.url") | ||||
|     context.configure(url=url) | ||||
|  | ||||
|     with context.begin_transaction(): | ||||
|         context.run_migrations() | ||||
|  | ||||
| def run_migrations_online(): | ||||
|     """Run migrations in 'online' mode. | ||||
|  | ||||
|     In this scenario we need to create an Engine | ||||
|     and associate a connection with the context. | ||||
|  | ||||
|     """ | ||||
|     engine = engine_from_config( | ||||
|                 config.get_section(config.config_ini_section), | ||||
|                 prefix='sqlalchemy.', | ||||
|                 poolclass=pool.NullPool) | ||||
|  | ||||
|     logger.info('Testing for an old alembic_version table.') | ||||
|  | ||||
|     connection = engine.connect() | ||||
|     context.configure( | ||||
|                 connection=connection, | ||||
|                 target_metadata=target_metadata, | ||||
|                 version_table='alembic_version' | ||||
|                 ) | ||||
|  | ||||
|     script_location = config.get_main_option('script_location') | ||||
|     found = False | ||||
|     mc = context.get_context() | ||||
|     current_db_revision = mc.get_current_revision() | ||||
|     script = ScriptDirectory.from_config(config) | ||||
|     """ If there was an existing alembic_version table, we need to | ||||
|     check that it's current revision is in the history for the tree | ||||
|     we're working with. | ||||
|     """ | ||||
|     for x in script.iterate_revisions('head', 'base'): | ||||
|         if x.revision == current_db_revision: | ||||
|             """ An alembic_versions table was found and it belongs to | ||||
|             this alembic tree | ||||
|             """ | ||||
|             logger.info( | ||||
|                 ('An old alembic_version table at revision %s was ' | ||||
|                  'found for %s.  Renaming to alembic_version_%s.'), | ||||
|                         current_db_revision, script_location, | ||||
|                         script_location) | ||||
|             op = Operations(mc) | ||||
|             try: | ||||
|                 with context.begin_transaction(): | ||||
|                     op.rename_table( | ||||
|                         'alembic_version', 'alembic_version_%s' | ||||
|                         % script_location) | ||||
|                 found = True | ||||
|             except: | ||||
|                 logger.error(('Unable to rename alembic_version to ' | ||||
|                              'alembic_version_%s.'), | ||||
|                              script_location) | ||||
|                 connection.close() | ||||
|                 return | ||||
|  | ||||
|             break | ||||
|  | ||||
|     if not found: | ||||
|         logger.info('Didn\'t find an old alembic_version table.') | ||||
|     logger.info('Trying alembic_version_%s.' % script_location) | ||||
|  | ||||
|     """ We MAY have an alembic_version table that doesn't belong to | ||||
|     this tree but if we still don't have an alembic_version_<tree> | ||||
|     table, alembic will create it. | ||||
|     """ | ||||
|     context.configure( | ||||
|                 connection=connection, | ||||
|                 target_metadata=target_metadata, | ||||
|                 version_table='alembic_version_' + script_location | ||||
|                 ) | ||||
|     mc = context.get_context() | ||||
|     current_db_revision = mc.get_current_revision() | ||||
|     if current_db_revision: | ||||
|         logger.info( | ||||
|             'Using the alembic_version_%s table at revision %s.', | ||||
|             script_location, current_db_revision) | ||||
|     else: | ||||
|         logger.info('Creating new alembic_version_%s table.', | ||||
|                     script_location) | ||||
|  | ||||
|     try: | ||||
|         with context.begin_transaction(): | ||||
|             context.run_migrations() | ||||
|     finally: | ||||
|         connection.close() | ||||
|  | ||||
|  | ||||
| if context.is_offline_mode(): | ||||
|     run_migrations_offline() | ||||
| else: | ||||
|     run_migrations_online() | ||||
|  | ||||
| @@ -1,74 +0,0 @@ | ||||
| from __future__ import with_statement | ||||
| from alembic import context | ||||
| from sqlalchemy import engine_from_config, pool | ||||
| from logging.config import fileConfig | ||||
|  | ||||
| # this is the Alembic Config object, which provides | ||||
| # access to the values within the .ini file in use. | ||||
| config = context.config | ||||
|  | ||||
| # Interpret the config file for Python logging. | ||||
| # This line sets up loggers basically. | ||||
| try: | ||||
|     fileConfig(config.config_file_name) | ||||
| except: | ||||
|     pass | ||||
|  | ||||
| # add your model's MetaData object here | ||||
| # for 'autogenerate' support | ||||
| # from myapp import mymodel | ||||
| # target_metadata = mymodel.Base.metadata | ||||
| target_metadata = None | ||||
|  | ||||
| # other values from the config, defined by the needs of env.py, | ||||
| # can be acquired: | ||||
| # my_important_option = config.get_main_option("my_important_option") | ||||
| # ... etc. | ||||
|  | ||||
| def run_migrations_offline(): | ||||
|     """Run migrations in 'offline' mode. | ||||
|  | ||||
|     This configures the context with just a URL | ||||
|     and not an Engine, though an Engine is acceptable | ||||
|     here as well.  By skipping the Engine creation | ||||
|     we don't even need a DBAPI to be available. | ||||
|  | ||||
|     Calls to context.execute() here emit the given string to the | ||||
|     script output. | ||||
|  | ||||
|     """ | ||||
|     url = config.get_main_option("sqlalchemy.url") | ||||
|     context.configure(url=url) | ||||
|  | ||||
|     with context.begin_transaction(): | ||||
|         context.run_migrations() | ||||
|  | ||||
| def run_migrations_online(): | ||||
|     """Run migrations in 'online' mode. | ||||
|  | ||||
|     In this scenario we need to create an Engine | ||||
|     and associate a connection with the context. | ||||
|  | ||||
|     """ | ||||
|     engine = engine_from_config( | ||||
|                 config.get_section(config.config_ini_section), | ||||
|                 prefix='sqlalchemy.', | ||||
|                 poolclass=pool.NullPool) | ||||
|  | ||||
|     connection = engine.connect() | ||||
|     context.configure( | ||||
|                 connection=connection, | ||||
|                 target_metadata=target_metadata | ||||
|                 ) | ||||
|  | ||||
|     try: | ||||
|         with context.begin_transaction(): | ||||
|             context.run_migrations() | ||||
|     finally: | ||||
|         connection.close() | ||||
|  | ||||
| if context.is_offline_mode(): | ||||
|     run_migrations_offline() | ||||
| else: | ||||
|     run_migrations_online() | ||||
|  | ||||
							
								
								
									
										1
									
								
								contrib/ast-db-manage/voicemail/env.py
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								contrib/ast-db-manage/voicemail/env.py
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | ||||
| ../env.py | ||||
		Reference in New Issue
	
	Block a user