Fix initialization of plugin_data table in AdminStore
[cascardo/ipsilon.git] / ipsilon / tools / dbupgrade.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2015 Ipsilon project Contributors, for license see COPYING
4
5 import cherrypy
6 import os
7 from jinja2 import Environment, FileSystemLoader
8 import ipsilon.util.sessions
9 from ipsilon.util.data import AdminStore, Store, UserStore, TranStore
10 from ipsilon.util.sessions import SqlSession
11 from ipsilon.root import Root
12
13
14 def _upgrade_database(datastore):
15     print 'Considering datastore %s' % datastore.__class__.__name__
16     # pylint: disable=protected-access
17     current_version = datastore._get_schema_version()
18     # pylint: disable=protected-access
19     code_schema_version = datastore._code_schema_version()
20     upgrade_required = False
21     if current_version is None:
22         # Initialize schema
23         print 'Initializing schema for %s' % datastore.__class__.__name__
24         upgrade_required = True
25     elif current_version != code_schema_version:
26         print 'Upgrading schema for %s' % datastore.__class__.__name__
27         upgrade_required = True
28     else:
29         print 'Schema for %s is up-to-date' % datastore.__class__.__name__
30     if upgrade_required:
31         if datastore.is_readonly:
32             print 'Datastore is readonly. Please fix manually!'
33             return False
34         try:
35             datastore.upgrade_database()
36         except Exception as ex:  # pylint: disable=broad-except
37             # Error upgrading database
38             print 'Error upgrading datastore: %s' % ex
39             return False
40         else:
41             # Upgrade went OK
42             return True
43     else:
44         return True
45
46
47 def upgrade_failed():
48     print 'Upgrade failed. Please fix errors above and retry'
49     raise Exception('Upgrading failed')
50
51
52 def execute_upgrade(cfgfile):
53     cherrypy.lib.sessions.SqlSession = ipsilon.util.sessions.SqlSession
54     cherrypy.config.update(cfgfile)
55
56     # pylint: disable=protected-access
57     Store._is_upgrade = True
58
59     adminstore = AdminStore()
60     # First try to upgrade the config store before continuing
61     if not _upgrade_database(adminstore):
62         return upgrade_failed()
63
64     admin_config = adminstore.load_config()
65     for option in admin_config:
66         cherrypy.config[option] = admin_config[option]
67
68     # Initialize a minimal env
69     template_env = Environment(loader=FileSystemLoader(
70         os.path.join(cherrypy.config['base.dir'],
71                      'templates')))
72     root = Root('default', template_env)
73
74     # Handle the session store if that is Sql
75     print 'Handling sessions datastore'
76     if cherrypy.config['tools.sessions.storage_type'] != 'sql':
77         print 'Not SQL-based, skipping'
78     else:
79         dburi = cherrypy.config['tools.sessions.storage_dburi']
80         SqlSession.setup(storage_dburi=dburi)
81         if not _upgrade_database(SqlSession._store):
82             return upgrade_failed()
83
84     # Now handle the rest of the default datastores
85     for store in [UserStore, TranStore]:
86         store = store()
87         print 'Handling default datastore %s' % store.__class__.__name__
88         if not _upgrade_database(store):
89             return upgrade_failed()
90
91     # And now datastores for any of the plugins
92     for facility in ['provider_config',
93                      'login_config',
94                      'info_config']:
95         for plugin in root._site[facility].enabled:
96             print 'Handling plugin %s' % plugin
97             plugin = root._site[facility].available[plugin]
98             print 'Creating plugin AdminStore table'
99             adminstore.create_plugin_data_table(plugin.name)
100             for store in plugin.used_datastores():
101                 print 'Handling plugin datastore %s' % store.__class__.__name__
102                 if not _upgrade_database(store):
103                     return upgrade_failed()
104
105     # We are done with the init/upgrade
106     # pylint: disable=protected-access
107     Store._is_upgrade = False