diff options
author | Matthew Jordan <mjordan@digium.com> | 2013-08-29 12:30:07 +0000 |
---|---|---|
committer | Matthew Jordan <mjordan@digium.com> | 2013-08-29 12:30:07 +0000 |
commit | 72cf2779e8a35c1bfc5cc63a7991c8900a712d5c (patch) | |
tree | 59bfba07fa62ae579994d26c7baca30bc95c2081 | |
parent | 186db8fdaf415f838c6c0bc29c9bd821ad3146c7 (diff) |
Actually *add* the database schema management utilities
In r397874, the scripts were removed... but not replaced. Thanks to
Michael Young for noticing this!
........
Merged revisions 397911 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397912 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | contrib/ast-db-manage/README.md | 63 | ||||
-rw-r--r-- | contrib/ast-db-manage/config.ini.sample | 48 | ||||
-rw-r--r-- | contrib/ast-db-manage/config/env.py | 71 | ||||
-rw-r--r-- | contrib/ast-db-manage/config/script.py.mako | 22 | ||||
-rw-r--r-- | contrib/ast-db-manage/config/versions/4da0c5f79a9c_create_tables.py | 292 | ||||
-rw-r--r-- | contrib/ast-db-manage/voicemail.ini.sample | 48 | ||||
-rw-r--r-- | contrib/ast-db-manage/voicemail/env.py | 71 | ||||
-rw-r--r-- | contrib/ast-db-manage/voicemail/script.py.mako | 22 | ||||
-rw-r--r-- | contrib/ast-db-manage/voicemail/versions/a2e9769475e_create_tables.py | 58 |
9 files changed, 695 insertions, 0 deletions
diff --git a/contrib/ast-db-manage/README.md b/contrib/ast-db-manage/README.md new file mode 100644 index 000000000..3444dd5cd --- /dev/null +++ b/contrib/ast-db-manage/README.md @@ -0,0 +1,63 @@ +Asterisk Database Manager +========================= + +Asterisk includes optional database integration for a variety of features. +The purpose of this effort is to assist in managing the database schema +for Asterisk database integration. + +This is implemented as a set of repositories that contain database schema +migrations, using [Alembic](http://alembic.readthedocs.org). The existing +repositories include: + + * `config` - Tables used for Asterisk realtime configuration + * `voicemail` - Tables used for `ODBC_STOARGE` of voicemail messages + +Alembic uses SQLAlchemy, which has support for +[many databases](http://docs.sqlalchemy.org/en/rel_0_8/dialects/index.html). + +IMPORTANT NOTE: This is brand new and the initial migrations are still subject +to change. Only use this for testing purposes for now. + +Example Usage +------------- + +First, create an ini file that contains database connection details. For help +with connection string details, see the +[SQLAlchemy docs](http://docs.sqlalchemy.org/en/rel_0_8/core/engines.html#database-urls). + + $ cp config.ini.sample config.ini + ... edit config.ini and change sqlalchemy.url ... + +Next, bring the database up to date with the current schema. + + $ alembic -c config.ini upgrade head + +In the future, as additional database migrations are added, you can run +alembic again to migrate the existing tables to the latest schema. + + $ alembic -c config.ini upgrade head + +The migrations support both upgrading and downgrading. You could go all the +way back to where you started with no tables by downgrading back to the base +revision. + + $ alembic -c config.ini downgrade base + +`base` and `head` are special revisions. You can refer to specific revisions +to upgrade or downgrade to, as well. + + $ alembic -c config.ini upgrade 4da0c5f79a9c + +Offline Mode +------------ + +If you would like to just generate the SQL statements that would have been +executed, you can use alembic's offline mode. + + $ alembic -c config.ini upgrade head --sql + +Adding Database Migrations +-------------------------- + +The best way to learn about how to add additional database migrations is to +refer to the [Alembic documentation](http://alembic.readthedocs.org). diff --git a/contrib/ast-db-manage/config.ini.sample b/contrib/ast-db-manage/config.ini.sample new file mode 100644 index 000000000..d6cfacd79 --- /dev/null +++ b/contrib/ast-db-manage/config.ini.sample @@ -0,0 +1,48 @@ +[alembic] +# path to migration scripts +script_location = config + +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + +sqlalchemy.url = mysql://root:password@localhost/asterisk + + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/contrib/ast-db-manage/config/env.py b/contrib/ast-db-manage/config/env.py new file mode 100644 index 000000000..f72400b10 --- /dev/null +++ b/contrib/ast-db-manage/config/env.py @@ -0,0 +1,71 @@ +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. +fileConfig(config.config_file_name) + +# 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() + diff --git a/contrib/ast-db-manage/config/script.py.mako b/contrib/ast-db-manage/config/script.py.mako new file mode 100644 index 000000000..95702017e --- /dev/null +++ b/contrib/ast-db-manage/config/script.py.mako @@ -0,0 +1,22 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision} +Create Date: ${create_date} + +""" + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} + +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/contrib/ast-db-manage/config/versions/4da0c5f79a9c_create_tables.py b/contrib/ast-db-manage/config/versions/4da0c5f79a9c_create_tables.py new file mode 100644 index 000000000..f6bed958b --- /dev/null +++ b/contrib/ast-db-manage/config/versions/4da0c5f79a9c_create_tables.py @@ -0,0 +1,292 @@ +# +# Asterisk -- An open source telephony toolkit. +# +# Copyright (C) 2013, Russell Bryant +# +# Russell Bryant <russell@rusellbryant.net> +# +# See http://www.asterisk.org for more information about +# the Asterisk project. Please do not directly contact +# any of the maintainers of this project for assistance; +# the project provides a web site, mailing lists and IRC +# channels for your use. +# +# This program is free software, distributed under the terms of +# the GNU General Public License Version 2. See the LICENSE file +# at the top of the source tree. +# + +"""Create tables + +Revision ID: 4da0c5f79a9c +Revises: None +Create Date: 2013-07-28 12:28:03.091587 + +""" + +# revision identifiers, used by Alembic. +revision = '4da0c5f79a9c' +down_revision = None + +from alembic import op +import sqlalchemy as sa + + +YESNO_VALUES = ['yes', 'no'] +TYPE_VALUES = ['friend', 'user', 'peer'] + +SIP_TRANSPORT_VALUES = ['udp', 'tcp', 'tls', 'ws', 'wss', 'udp,tcp', 'tcp,udp'] +SIP_DTMFMODE_VALUES = ['rfc2833', 'info', 'shortinfo', 'inband', 'auto'] +SIP_DIRECTMEDIA_VALUES = ['yes', 'no', 'nonat', 'update'] +SIP_PROGRESSINBAND_VALUES = ['yes', 'no', 'never'] +SIP_SESSION_TIMERS_VALUES = ['accept', 'refuse', 'originate'] +SIP_SESSION_REFRESHER_VALUES = ['uac', 'uas'] +SIP_CALLINGPRES_VALUES = ['allowed_not_screened', 'allowed_passed_screen', + 'allowed_failed_screen', 'allowed', + 'prohib_not_screened', 'prohib_passed_screen', + 'prohib_failed_screen', 'prohib'] + +IAX_REQUIRECALLTOKEN_VALUES = ['yes', 'no', 'auto'] +IAX_ENCRYPTION_VALUES = ['yes', 'no', 'aes128'] +IAX_TRANSFER_VALUES = ['yes', 'no', 'mediaonly'] + +MOH_MODE_VALUES = ['custom', 'files', 'mp3nb', 'quietmp3nb', 'quietmp3'] + + +def upgrade(): + op.create_table( + 'sippeers', + sa.Column('id', sa.Integer, primary_key=True, nullable=False, + autoincrement=True), + sa.Column('name', sa.String(40), nullable=False, unique=True), + sa.Column('ipaddr', sa.String(45)), + sa.Column('port', sa.Integer), + sa.Column('regseconds', sa.Integer), + sa.Column('defaultuser', sa.String(40)), + sa.Column('fullcontact', sa.String(80)), + sa.Column('regserver', sa.String(20)), + sa.Column('useragent', sa.String(20)), + sa.Column('lastms', sa.Integer), + sa.Column('host', sa.String(40)), + sa.Column('type', sa.Enum(*TYPE_VALUES)), + sa.Column('context', sa.String(40)), + sa.Column('permit', sa.String(95)), + sa.Column('deny', sa.String(95)), + sa.Column('secret', sa.String(40)), + sa.Column('md5secret', sa.String(40)), + sa.Column('remotesecret', sa.String(40)), + sa.Column('transport', sa.Enum(*SIP_TRANSPORT_VALUES)), + sa.Column('dtmfmode', sa.Enum(*SIP_DTMFMODE_VALUES)), + sa.Column('directmedia', sa.Enum(*SIP_DIRECTMEDIA_VALUES)), + sa.Column('nat', sa.String(29)), + sa.Column('callgroup', sa.String(40)), + sa.Column('pickupgroup', sa.String(40)), + sa.Column('language', sa.String(40)), + sa.Column('disallow', sa.String(200)), + sa.Column('allow', sa.String(200)), + sa.Column('insecure', sa.String(40)), + sa.Column('trustrpid', sa.Enum(*YESNO_VALUES)), + sa.Column('progressinband', sa.Enum(*SIP_PROGRESSINBAND_VALUES)), + sa.Column('promiscredir', sa.Enum(*YESNO_VALUES)), + sa.Column('useclientcode', sa.Enum(*YESNO_VALUES)), + sa.Column('accountcode', sa.String(40)), + sa.Column('setvar', sa.String(200)), + sa.Column('callerid', sa.String(40)), + sa.Column('amaflags', sa.String(40)), + sa.Column('callcounter', sa.Enum(*YESNO_VALUES)), + sa.Column('busylevel', sa.Integer), + sa.Column('allowoverlap', sa.Enum(*YESNO_VALUES)), + sa.Column('allowsubscribe', sa.Enum(*YESNO_VALUES)), + sa.Column('videosupport', sa.Enum(*YESNO_VALUES)), + sa.Column('maxcallbitrate', sa.Integer), + sa.Column('rfc2833compensate', sa.Enum(*YESNO_VALUES)), + sa.Column('mailbox', sa.String(40)), + sa.Column('session-timers', sa.Enum(*SIP_SESSION_TIMERS_VALUES)), + sa.Column('session-expires', sa.Integer), + sa.Column('session-minse', sa.Integer), + sa.Column('session-refresher', sa.Enum(*SIP_SESSION_REFRESHER_VALUES)), + sa.Column('t38pt_usertpsource', sa.String(40)), + sa.Column('regexten', sa.String(40)), + sa.Column('fromdomain', sa.String(40)), + sa.Column('fromuser', sa.String(40)), + sa.Column('qualify', sa.String(40)), + sa.Column('defaultip', sa.String(45)), + sa.Column('rtptimeout', sa.Integer), + sa.Column('rtpholdtimeout', sa.Integer), + sa.Column('sendrpid', sa.Enum(*YESNO_VALUES)), + sa.Column('outboundproxy', sa.String(40)), + sa.Column('callbackextension', sa.String(40)), + sa.Column('timert1', sa.Integer), + sa.Column('timerb', sa.Integer), + sa.Column('qualifyfreq', sa.Integer), + sa.Column('constantssrc', sa.Enum(*YESNO_VALUES)), + sa.Column('contactpermit', sa.String(95)), + sa.Column('contactdeny', sa.String(95)), + sa.Column('usereqphone', sa.Enum(*YESNO_VALUES)), + sa.Column('textsupport', sa.Enum(*YESNO_VALUES)), + sa.Column('faxdetect', sa.Enum(*YESNO_VALUES)), + sa.Column('buggymwi', sa.Enum(*YESNO_VALUES)), + sa.Column('auth', sa.String(40)), + sa.Column('fullname', sa.String(40)), + sa.Column('trunkname', sa.String(40)), + sa.Column('cid_number', sa.String(40)), + sa.Column('callingpres', sa.Enum(*SIP_CALLINGPRES_VALUES)), + sa.Column('mohinterpret', sa.String(40)), + sa.Column('mohsuggest', sa.String(40)), + sa.Column('parkinglot', sa.String(40)), + sa.Column('hasvoicemail', sa.Enum(*YESNO_VALUES)), + sa.Column('subscribemwi', sa.Enum(*YESNO_VALUES)), + sa.Column('vmexten', sa.String(40)), + sa.Column('autoframing', sa.Enum(*YESNO_VALUES)), + sa.Column('rtpkeepalive', sa.Integer), + sa.Column('call-limit', sa.Integer), + sa.Column('g726nonstandard', sa.Enum(*YESNO_VALUES)), + sa.Column('ignoresdpversion', sa.Enum(*YESNO_VALUES)), + sa.Column('allowtransfer', sa.Enum(*YESNO_VALUES)), + sa.Column('dynamic', sa.Enum(*YESNO_VALUES)), + sa.Column('path', sa.String(256)), + sa.Column('supportpath', sa.Enum(*YESNO_VALUES)) + ) + op.create_index('sippeers_name', 'sippeers', ['name']) + op.create_index('sippeers_name_host', 'sippeers', ['name', 'host']) + op.create_index('sippeers_ipaddr_port', 'sippeers', ['ipaddr', 'port']) + op.create_index('sippeers_host_port', 'sippeers', ['host', 'port']) + + op.create_table( + 'iaxfriends', + sa.Column('id', sa.Integer, primary_key=True, nullable=False, + autoincrement=True), + sa.Column('name', sa.String(40), nullable=False, unique=True), + sa.Column('type', sa.Enum(*TYPE_VALUES)), + sa.Column('username', sa.String(40)), + sa.Column('mailbox', sa.String(40)), + sa.Column('secret', sa.String(40)), + sa.Column('dbsecret', sa.String(40)), + sa.Column('context', sa.String(40)), + sa.Column('regcontext', sa.String(40)), + sa.Column('host', sa.String(40)), + sa.Column('ipaddr', sa.String(40)), + sa.Column('port', sa.Integer), + sa.Column('defaultip', sa.String(20)), + sa.Column('sourceaddress', sa.String(20)), + sa.Column('mask', sa.String(20)), + sa.Column('regexten', sa.String(40)), + sa.Column('regseconds', sa.Integer), + sa.Column('accountcode', sa.String(20)), + sa.Column('mohinterpret', sa.String(20)), + sa.Column('mohsuggest', sa.String(20)), + sa.Column('inkeys', sa.String(40)), + sa.Column('outkeys', sa.String(40)), + sa.Column('language', sa.String(10)), + sa.Column('callerid', sa.String(100)), + sa.Column('cid_number', sa.String(40)), + sa.Column('sendani', sa.Enum(*YESNO_VALUES)), + sa.Column('fullname', sa.String(40)), + sa.Column('trunk', sa.Enum(*YESNO_VALUES)), + sa.Column('auth', sa.String(20)), + sa.Column('maxauthreq', sa.Integer), + sa.Column('requirecalltoken', sa.Enum(*IAX_REQUIRECALLTOKEN_VALUES)), + sa.Column('encryption', sa.Enum(*IAX_ENCRYPTION_VALUES)), + sa.Column('transfer', sa.Enum(*IAX_TRANSFER_VALUES)), + sa.Column('jitterbuffer', sa.Enum(*YESNO_VALUES)), + sa.Column('forcejitterbuffer', sa.Enum(*YESNO_VALUES)), + sa.Column('disallow', sa.String(200)), + sa.Column('allow', sa.String(200)), + sa.Column('codecpriority', sa.String(40)), + sa.Column('qualify', sa.String(10)), + sa.Column('qualifysmoothing', sa.Enum(*YESNO_VALUES)), + sa.Column('qualifyfreqok', sa.String(10)), + sa.Column('qualifyfreqnotok', sa.String(10)), + sa.Column('timezone', sa.String(20)), + sa.Column('adsi', sa.Enum(*YESNO_VALUES)), + sa.Column('amaflags', sa.String(20)), + sa.Column('setvar', sa.String(200)) + ) + op.create_index('iaxfriends_name', 'iaxfriends', ['name']) + op.create_index('iaxfriends_name_host', 'iaxfriends', ['name', 'host']) + op.create_index('iaxfriends_name_ipaddr_port', 'iaxfriends', + ['name', 'ipaddr', 'port']) + op.create_index('iaxfriends_ipaddr_port', 'iaxfriends', ['ipaddr', 'port']) + op.create_index('iaxfriends_host_port', 'iaxfriends', ['host', 'port']) + + op.create_table( + 'voicemail', + sa.Column('uniqueid', sa.Integer, primary_key=True, nullable=False, + autoincrement=True), + sa.Column('context', sa.String(80), nullable=False), + sa.Column('mailbox', sa.String(80), nullable=False), + sa.Column('password', sa.String(80), nullable=False), + sa.Column('fullname', sa.String(80)), + sa.Column('alias', sa.String(80)), + sa.Column('email', sa.String(80)), + sa.Column('pager', sa.String(80)), + sa.Column('attach', sa.Enum(*YESNO_VALUES)), + sa.Column('attachfmt', sa.String(10)), + sa.Column('serveremail', sa.String(80)), + sa.Column('language', sa.String(20)), + sa.Column('tz', sa.String(30)), + sa.Column('deletevoicemail', sa.Enum(*YESNO_VALUES)), + sa.Column('saycid', sa.Enum(*YESNO_VALUES)), + sa.Column('sendvoicemail', sa.Enum(*YESNO_VALUES)), + sa.Column('review', sa.Enum(*YESNO_VALUES)), + sa.Column('tempgreetwarn', sa.Enum(*YESNO_VALUES)), + sa.Column('operator', sa.Enum(*YESNO_VALUES)), + sa.Column('envelope', sa.Enum(*YESNO_VALUES)), + sa.Column('sayduration', sa.Integer), + sa.Column('forcename', sa.Enum(*YESNO_VALUES)), + sa.Column('forcegreetings', sa.Enum(*YESNO_VALUES)), + sa.Column('callback', sa.String(80)), + sa.Column('dialout', sa.String(80)), + sa.Column('exitcontext', sa.String(80)), + sa.Column('maxmsg', sa.Integer), + sa.Column('volgain', sa.Numeric(precision=5, scale=2)), + sa.Column('imapuser', sa.String(80)), + sa.Column('imappassword', sa.String(80)), + sa.Column('imapserver', sa.String(80)), + sa.Column('imapport', sa.String(8)), + sa.Column('imapflags', sa.String(80)), + sa.Column('stamp', sa.DateTime()) + ) + op.create_index('voicemail_mailbox', 'voicemail', ['mailbox']) + op.create_index('voicemail_context', 'voicemail', ['context']) + op.create_index('voicemail_mailbox_context', 'voicemail', ['mailbox', 'context']) + op.create_index('voicemail_imapuser', 'voicemail', ['imapuser']) + + op.create_table( + 'meetme', + sa.Column('bookid', sa.Integer, primary_key=True, nullable=False, + autoincrement=True), + sa.Column('confno', sa.String(80), nullable=False), + sa.Column('starttime', sa.DateTime()), + sa.Column('endtime', sa.DateTime()), + sa.Column('pin', sa.String(20)), + sa.Column('adminpin', sa.String(20)), + sa.Column('opts', sa.String(20)), + sa.Column('adminopts', sa.String(20)), + sa.Column('recordingfilename', sa.String(80)), + sa.Column('recordingformat', sa.String(10)), + sa.Column('maxusers', sa.Integer), + sa.Column('members', sa.Integer, nullable=False, default=0) + ) + op.create_index('meetme_confno_starttime_endtime', 'meetme', + ['confno', 'starttime', 'endtime']) + + op.create_table( + 'musiconhold', + sa.Column('name', sa.String(80), primary_key=True, nullable=False), + sa.Column('mode', sa.Enum(*MOH_MODE_VALUES)), + sa.Column('directory', sa.String(255)), + sa.Column('application', sa.String(255)), + sa.Column('digit', sa.String(1)), + sa.Column('sort', sa.String(10)), + sa.Column('format', sa.String(10)), + sa.Column('stamp', sa.DateTime()) + ) + + +def downgrade(): + op.drop_table('sippeers') + op.drop_table('iaxfriends') + op.drop_table('voicemail') + op.drop_table('meetme') + op.drop_table('musiconhold') diff --git a/contrib/ast-db-manage/voicemail.ini.sample b/contrib/ast-db-manage/voicemail.ini.sample new file mode 100644 index 000000000..6742d019e --- /dev/null +++ b/contrib/ast-db-manage/voicemail.ini.sample @@ -0,0 +1,48 @@ +[alembic] +# path to migration scripts +script_location = voicemail + +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + +sqlalchemy.url = mysql://user:pass@localhost/voicemail + + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/contrib/ast-db-manage/voicemail/env.py b/contrib/ast-db-manage/voicemail/env.py new file mode 100644 index 000000000..f72400b10 --- /dev/null +++ b/contrib/ast-db-manage/voicemail/env.py @@ -0,0 +1,71 @@ +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. +fileConfig(config.config_file_name) + +# 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() + diff --git a/contrib/ast-db-manage/voicemail/script.py.mako b/contrib/ast-db-manage/voicemail/script.py.mako new file mode 100644 index 000000000..95702017e --- /dev/null +++ b/contrib/ast-db-manage/voicemail/script.py.mako @@ -0,0 +1,22 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision} +Create Date: ${create_date} + +""" + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} + +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/contrib/ast-db-manage/voicemail/versions/a2e9769475e_create_tables.py b/contrib/ast-db-manage/voicemail/versions/a2e9769475e_create_tables.py new file mode 100644 index 000000000..3dc4d47c4 --- /dev/null +++ b/contrib/ast-db-manage/voicemail/versions/a2e9769475e_create_tables.py @@ -0,0 +1,58 @@ +# +# Asterisk -- An open source telephony toolkit. +# +# Copyright (C) 2013, Russell Bryant +# +# Russell Bryant <russell@rusellbryant.net> +# +# See http://www.asterisk.org for more information about +# the Asterisk project. Please do not directly contact +# any of the maintainers of this project for assistance; +# the project provides a web site, mailing lists and IRC +# channels for your use. +# +# This program is free software, distributed under the terms of +# the GNU General Public License Version 2. See the LICENSE file +# at the top of the source tree. +# + +"""Create tables + +Revision ID: a2e9769475e +Revises: None +Create Date: 2013-07-29 23:43:09.431668 + +""" + +# revision identifiers, used by Alembic. +revision = 'a2e9769475e' +down_revision = None + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.create_table( + 'voicemail_messages', + sa.Column('dir', sa.String(255), nullable=False), + sa.Column('msgnum', sa.Integer, nullable=False), + sa.Column('context', sa.String(80)), + sa.Column('macrocontext', sa.String(80)), + sa.Column('callerid', sa.String(80)), + sa.Column('origtime', sa.Integer), + sa.Column('duration', sa.Integer), + sa.Column('recording', sa.LargeBinary), + sa.Column('flag', sa.String(30)), + sa.Column('category', sa.String(30)), + sa.Column('mailboxuser', sa.String(30)), + sa.Column('mailboxcontext', sa.String(30)), + sa.Column('msg_id', sa.String(40)) + ) + op.create_primary_key('voicemail_messages_dir_msgnum', + 'voicemail_messages', ['dir', 'msgnum']) + op.create_index('voicemail_messages_dir', 'voicemail_messages', ['dir']) + + +def downgrade(): + op.drop_table('voicemail_messages') |