1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 from sqlalchemy
.orm
import sessionmaker
22 from mediagoblin
.db
.open import setup_connection_and_db_from_config
23 from mediagoblin
.db
.migration_tools
import MigrationManager
, AlembicMigrationManager
24 from mediagoblin
.init
import setup_global_and_app_config
25 from mediagoblin
.tools
.common
import import_component
27 _log
= logging
.getLogger(__name__
)
29 ## Let's not set the level as debug by default to avoid confusing users :)
30 # _log.setLevel(logging.DEBUG)
33 def dbupdate_parse_setup(subparser
):
37 class DatabaseData(object):
38 def __init__(self
, name
, models
, foundations
, migrations
):
41 self
.foundations
= foundations
42 self
.migrations
= migrations
44 def make_migration_manager(self
, session
):
45 return MigrationManager(
46 self
.name
, self
.models
, self
.foundations
, self
.migrations
, session
)
49 def gather_database_data(plugins
):
51 Gather all database data relevant to the extensions installed.
53 Gather all database data relevant to the extensions we have
54 installed so we can do migrations and table initialization.
56 Returns a list of DatabaseData objects.
61 from mediagoblin
.db
.models
import MODELS
as MAIN_MODELS
62 from mediagoblin
.db
.migrations
import MIGRATIONS
as MAIN_MIGRATIONS
63 from mediagoblin
.db
.models
import FOUNDATIONS
as MAIN_FOUNDATIONS
65 managed_dbdata
.append(
67 u
'__main__', MAIN_MODELS
, MAIN_FOUNDATIONS
, MAIN_MIGRATIONS
))
69 for plugin
in plugins
:
71 models
= import_component('{0}.models:MODELS'.format(plugin
))
72 except ImportError as exc
:
73 _log
.debug('No models found for {0}: {1}'.format(
78 except AttributeError as exc
:
79 _log
.warning('Could not find MODELS in {0}.models, have you '
80 'forgotten to add it? ({1})'.format(plugin
, exc
))
84 migrations
= import_component('{0}.migrations:MIGRATIONS'.format(
86 except ImportError as exc
:
87 _log
.debug('No migrations found for {0}: {1}'.format(
92 except AttributeError as exc
:
93 _log
.debug('Could not find MIGRATIONS in {0}.migrations, have you'
94 'forgotten to add it? ({1})'.format(plugin
, exc
))
98 foundations
= import_component(
99 '{0}.models:FOUNDATIONS'.format(plugin
))
100 except ImportError as exc
:
102 except AttributeError as exc
:
106 managed_dbdata
.append(
107 DatabaseData(plugin
, models
, foundations
, migrations
))
109 return managed_dbdata
112 def run_alembic_migrations(db
, app_config
, global_config
):
113 """Initialize a database and runs all Alembic migrations."""
114 Session
= sessionmaker(bind
=db
.engine
)
115 manager
= AlembicMigrationManager(Session())
116 manager
.init_or_migrate()
119 def run_dbupdate(app_config
, global_config
):
121 Initialize or migrate the database as specified by the config file.
123 Will also initialize or migrate all extensions (media types, and
124 in the future, plugins)
126 # Set up the database
127 db
= setup_connection_and_db_from_config(app_config
, migrations
=True)
129 run_all_migrations(db
, app_config
, global_config
)
131 # TODO: Make this happen regardless of python 2 or 3 once ensured
133 run_alembic_migrations(db
, app_config
, global_config
)
136 def run_all_migrations(db
, app_config
, global_config
):
137 """Initialize or migrates a database.
139 Initializes or migrates a database that already has a
140 connection setup and also initializes or migrates all
141 extensions based on the config files.
143 It can be used to initialize an in-memory database for
146 # Gather information from all media managers / projects
147 dbdatas
= gather_database_data(
148 list(global_config
.get('plugins', {}).keys()))
150 Session
= sessionmaker(bind
=db
.engine
)
152 # Setup media managers for all dbdata, run init/migrate and print info
153 # For each component, create/migrate tables
154 for dbdata
in dbdatas
:
155 migration_manager
= dbdata
.make_migration_manager(Session())
156 migration_manager
.init_or_migrate()
160 global_config
, app_config
= setup_global_and_app_config(args
.conf_file
)
161 run_dbupdate(app_config
, global_config
)