Fix a comment.
[mediagoblin.git] / mediagoblin / gmg_commands / dbupdate.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
3 #
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.
8 #
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.
13 #
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/>.
16
17 import logging
18
19 from sqlalchemy.orm import sessionmaker
20
21 from mediagoblin.db.open import setup_connection_and_db_from_config
22 from mediagoblin.db.migration_tools import MigrationManager
23 from mediagoblin.init import setup_global_and_app_config
24 from mediagoblin.tools.common import import_component
25
26 _log = logging.getLogger(__name__)
27 logging.basicConfig()
28 ## Let's not set the level as debug by default to avoid confusing users :)
29 # _log.setLevel(logging.DEBUG)
30
31
32 def dbupdate_parse_setup(subparser):
33 pass
34
35
36 class DatabaseData(object):
37 def __init__(self, name, models, foundations, migrations):
38 self.name = name
39 self.models = models
40 self.foundations = foundations
41 self.migrations = migrations
42
43 def make_migration_manager(self, session):
44 return MigrationManager(
45 self.name, self.models, self.foundations, self.migrations, session)
46
47
48 def gather_database_data(plugins):
49 """
50 Gather all database data relevant to the extensions we have
51 installed so we can do migrations and table initialization.
52
53 Returns a list of DatabaseData objects.
54 """
55 managed_dbdata = []
56
57 # Add main first
58 from mediagoblin.db.models import MODELS as MAIN_MODELS
59 from mediagoblin.db.migrations import MIGRATIONS as MAIN_MIGRATIONS
60 from mediagoblin.db.models import FOUNDATIONS as MAIN_FOUNDATIONS
61
62 managed_dbdata.append(
63 DatabaseData(
64 u'__main__', MAIN_MODELS, MAIN_FOUNDATIONS, MAIN_MIGRATIONS))
65
66 for plugin in plugins:
67 try:
68 models = import_component('{0}.models:MODELS'.format(plugin))
69 except ImportError as exc:
70 _log.debug('No models found for {0}: {1}'.format(
71 plugin,
72 exc))
73
74 models = []
75 except AttributeError as exc:
76 _log.warning('Could not find MODELS in {0}.models, have you \
77 forgotten to add it? ({1})'.format(plugin, exc))
78 models = []
79
80 try:
81 migrations = import_component('{0}.migrations:MIGRATIONS'.format(
82 plugin))
83 except ImportError as exc:
84 _log.debug('No migrations found for {0}: {1}'.format(
85 plugin,
86 exc))
87
88 migrations = {}
89 except AttributeError as exc:
90 _log.debug('Could not find MIGRATIONS in {0}.migrations, have you \
91 forgotten to add it? ({1})'.format(plugin, exc))
92 migrations = {}
93
94 try:
95 foundations = import_component('{0}.models:FOUNDATIONS'.format(plugin))
96 except ImportError as exc:
97 foundations = {}
98 except AttributeError as exc:
99 foundations = {}
100
101 if models:
102 managed_dbdata.append(
103 DatabaseData(plugin, models, foundations, migrations))
104
105
106 return managed_dbdata
107
108
109 def run_dbupdate(app_config, global_config):
110 """
111 Initialize or migrate the database as specified by the config file.
112
113 Will also initialize or migrate all extensions (media types, and
114 in the future, plugins)
115 """
116
117 # Set up the database
118 db = setup_connection_and_db_from_config(app_config, migrations=True)
119 # Run the migrations
120 run_all_migrations(db, app_config, global_config)
121
122
123 def run_all_migrations(db, app_config, global_config):
124 """
125 Initializes or migrates a database that already has a
126 connection setup and also initializes or migrates all
127 extensions based on the config files.
128
129 It can be used to initialize an in-memory database for
130 testing.
131 """
132 # Gather information from all media managers / projects
133 dbdatas = gather_database_data(
134 global_config.get('plugins', {}).keys())
135
136 Session = sessionmaker(bind=db.engine)
137
138 # Setup media managers for all dbdata, run init/migrate and print info
139 # For each component, create/migrate tables
140 for dbdata in dbdatas:
141 migration_manager = dbdata.make_migration_manager(Session())
142 migration_manager.init_or_migrate()
143
144
145 def dbupdate(args):
146 global_config, app_config = setup_global_and_app_config(args.conf_file)
147 run_dbupdate(app_config, global_config)