3 # Copyright (C) 2015 Ipsilon project Contributors, for license see COPYING
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
15 logger = logging.getLogger(__name__)
18 def _upgrade_database(datastore):
19 logger.debug('Considering datastore %s', datastore.__class__.__name__)
20 # pylint: disable=protected-access
21 current_version = datastore._get_schema_version()
22 # pylint: disable=protected-access
23 code_schema_version = datastore._code_schema_version()
24 upgrade_required = False
25 if current_version is None:
27 logger.debug('Initializing schema for %s',
28 datastore.__class__.__name__)
29 upgrade_required = True
30 elif current_version != code_schema_version:
31 logger.debug('Upgrading schema for %s', datastore.__class__.__name__)
32 upgrade_required = True
34 logger.debug('Schema for %s is up-to-date',
35 datastore.__class__.__name__)
37 if datastore.is_readonly:
38 logger.warning('Datastore is readonly. Please fix manually!')
41 datastore.upgrade_database()
42 except Exception as ex: # pylint: disable=broad-except
43 # Error upgrading database
44 logger.error('Error upgrading datastore: %s', ex)
54 logger.error('Upgrade failed. Please fix errors above and retry')
55 raise Exception('Upgrading failed')
58 def execute_upgrade(cfgfile):
59 cherrypy.lib.sessions.SqlSession = ipsilon.util.sessions.SqlSession
60 cherrypy.config.update(cfgfile)
62 # pylint: disable=protected-access
63 Store._is_upgrade = True
65 adminstore = AdminStore()
66 # First try to upgrade the config store before continuing
67 if not _upgrade_database(adminstore):
68 return upgrade_failed()
70 admin_config = adminstore.load_config()
71 for option in admin_config:
72 cherrypy.config[option] = admin_config[option]
74 # Initialize a minimal env
75 template_env = Environment(loader=FileSystemLoader(
76 os.path.join(cherrypy.config['base.dir'],
78 root = Root('default', template_env)
80 # Handle the session store if that is Sql
81 logger.debug('Handling sessions datastore')
82 if cherrypy.config['tools.sessions.storage_type'] != 'sql':
83 logger.debug('Not SQL-based, skipping')
85 dburi = cherrypy.config['tools.sessions.storage_dburi']
86 SqlSession.setup(storage_dburi=dburi)
87 if not _upgrade_database(SqlSession._store):
88 return upgrade_failed()
90 # Now handle the rest of the default datastores
91 for store in [UserStore, TranStore]:
93 logger.debug('Handling default datastore %s',
94 store.__class__.__name__)
95 if not _upgrade_database(store):
96 return upgrade_failed()
98 # And now datastores for any of the plugins
99 userstore = UserStore()
100 for facility in ['provider_config',
103 for plugin in root._site[facility].enabled:
104 logger.debug('Handling plugin %s', plugin)
105 plugin = root._site[facility].available[plugin]
106 logger.debug('Creating plugin AdminStore table')
107 adminstore.create_plugin_data_table(plugin.name)
108 logger.debug('Creating plugin UserStore table')
109 userstore.create_plugin_data_table(plugin.name)
110 for store in plugin.used_datastores():
111 logger.debug('Handling plugin datastore %s',
112 store.__class__.__name__)
113 if not _upgrade_database(store):
114 return upgrade_failed()
116 # We are done with the init/upgrade
117 # pylint: disable=protected-access
118 Store._is_upgrade = False