ipsilon-server-install sometimes fails to log & emit errors
[cascardo/ipsilon.git] / ipsilon / install / ipsilon-server-install
index 85f2ba3..74d995c 100755 (executable)
@@ -6,7 +6,7 @@ from ipsilon.info.common import InfoProviderInstall
 from ipsilon.providers.common import ProvidersInstall
 from ipsilon.helpers.common import EnvHelpersInstall
 from ipsilon.util.data import UserStore
-from ipsilon.tools import files
+from ipsilon.tools import files, dbupgrade
 import ConfigParser
 import argparse
 import cherrypy
@@ -27,17 +27,14 @@ DATADIR = '/var/lib/ipsilon'
 HTTPDCONFD = '/etc/httpd/conf.d'
 BINDIR = '/usr/libexec'
 STATICDIR = '/usr/share/ipsilon'
+CACHEDIR = '/var/cache/ipsilon'
 WSGI_SOCKET_PREFIX = None
 
 
-class ConfigurationError(Exception):
+class ConfigurationError(StandardError):
 
     def __init__(self, message):
-        super(ConfigurationError, self).__init__(message)
-        self.message = message
-
-    def __str__(self):
-        return repr(self.message)
+        StandardError.__init__(self, message)
 
 
 #Silence cherrypy logging to screen
@@ -100,14 +97,19 @@ def install(plugins, args):
                 'publicdatadir': args['public_data_dir'],
                 'wellknowndir': args['wellknown_dir'],
                 'sysuser': args['system_user'],
+                'cleanup_interval': args['cleanup_interval'],
                 'ipsilondir': BINDIR,
                 'staticdir': STATICDIR,
+                'cachedir': CACHEDIR,
                 'admindb': args['admin_dburi'] or args['database_url'] % {
                     'datadir': args['data_dir'], 'dbname': 'adminconfig'},
                 'usersdb': args['users_dburi'] or args['database_url'] % {
                     'datadir': args['data_dir'], 'dbname': 'userprefs'},
                 'transdb': args['transaction_dburi'] or args['database_url'] %
                 {'datadir': args['data_dir'], 'dbname': 'transactions'},
+                'samlsessionsdb': args['samlsessions_dburi'] or args[
+                    'database_url'] % {'datadir': args['data_dir'],
+                                       'dbname': 'saml2sessions'},
                 'secure': "False" if args['secure'] == "no" else "True",
                 'debugging': "True" if args['server_debugging'] else "False"}
     # Testing database sessions
@@ -161,15 +163,18 @@ def install(plugins, args):
                'info_provider': {},
                'auth_provider': {}}
 
-    # Move pre-existing admin db away
+    # Move pre-existing dbs away
     admin_db = cherrypy.config['admin.config.db']
     if os.path.exists(admin_db):
         shutil.move(admin_db, '%s.backup.%s' % (admin_db, now))
-
-    # Rebuild user db
     users_db = cherrypy.config['user.prefs.db']
     if os.path.exists(users_db):
         shutil.move(users_db, '%s.backup.%s' % (users_db, now))
+
+    # Initialize initial database schemas
+    dbupgrade.execute_upgrade(ipsilon_conf)
+
+    # Store primary admin
     db = UserStore()
     db.save_user_preferences(args['admin_user'], {'is_admin': 1})
 
@@ -178,7 +183,8 @@ def install(plugins, args):
         plugin = plugins['Environment Helpers'][plugin_name]
         plugin_changes = {}
         if plugin.configure_server(args, plugin_changes) == False:
-            logger.info('Configuration of environment helper %s failed' % plugin_name)
+            msg = 'Configuration of environment helper %s failed' % plugin_name
+            raise ConfigurationError(msg)
         changes['env_helper'][plugin_name] = plugin_changes
 
     logger.info('Configuring login managers')
@@ -189,7 +195,8 @@ def install(plugins, args):
             sys.exit('Login provider %s not installed' % plugin_name)
         plugin_changes = {}
         if plugin.configure(args, plugin_changes) == False:
-            logger.info('Configuration of login manager %s failed' % plugin_name)
+            msg = 'Configuration of login manager %s failed' % plugin_name
+            raise ConfigurationError(msg)
         changes['login_manager'][plugin_name] = plugin_changes
 
     logger.info('Configuring Info provider')
@@ -197,7 +204,8 @@ def install(plugins, args):
         plugin = plugins['Info Provider'][plugin_name]
         plugin_changes = {}
         if plugin.configure(args, plugin_changes) == False:
-            logger.info('Configuration of info provider %s failed' % plugin_name)
+            msg = 'Configuration of info provider %s failed' % plugin_name
+            raise ConfigurationError(msg)
         changes['info_provider'][plugin_name] = plugin_changes
 
     logger.info('Configuring Authentication Providers')
@@ -205,7 +213,8 @@ def install(plugins, args):
         plugin = plugins['Auth Providers'][plugin_name]
         plugin_changes = {}
         if plugin.configure(args, plugin_changes) == False:
-            logger.info('Configuration of auth provider %s failed' % plugin_name)
+            msg = 'Configuration of auth provider %s failed' % plugin_name
+            raise ConfigurationError(msg)
         changes['auth_provider'][plugin_name] = plugin_changes
 
     # Save any changes that were made
@@ -214,6 +223,9 @@ def install(plugins, args):
     with open(install_changes, 'w+') as f:
         f.write(changes)
 
+    # Initialize extra database schemas
+    dbupgrade.execute_upgrade(ipsilon_conf)
+
     # Fixup permissions so only the ipsilon user can read these files
     files.fix_user_dirs(instance_conf, opts['system_user'])
     files.fix_user_dirs(args['data_dir'], opts['system_user'])
@@ -231,6 +243,15 @@ def uninstall(plugins, args):
                               'ipsilon-%s.conf' % args['instance'])
     data_dir = os.path.join(DATADIR, args['instance'])
 
+    try:
+        tconf = ConfigParser.SafeConfigParser()
+        tconf.read(os.path.join(instance_conf, 'ipsilon.conf'))
+        cache_dir = tconf.get('global', 'cache_dir')
+    except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
+        cache_dir = None
+    else:
+        cache_dir = cache_dir.replace('"', '')
+
     if not os.path.exists(instance_conf):
         raise Exception('Could not find instance %s configuration'
                         % args['instance'])
@@ -283,6 +304,9 @@ def uninstall(plugins, args):
     shutil.rmtree(instance_conf)
     logger.info('Erasing instance data')
     shutil.rmtree(data_dir)
+    if cache_dir and os.path.exists(cache_dir):
+        for fn in os.listdir(cache_dir):
+            os.unlink(os.path.join(cache_dir, fn))
     logger.info('Uninstalled instance %s' % args['instance'])
 
 
@@ -310,7 +334,7 @@ def parse_config_profile(args):
             if g in globals():
                 globals()[g] = val
             else:
-                for k in globals().keys():
+                for k in globals():
                     if k.lower() == g.lower():
                         globals()[k] = val
                         break
@@ -357,6 +381,12 @@ def parse_args(plugins):
                              'template)')
     parser.add_argument('--transaction-dburi',
                         help='Transaction database URI (override template)')
+    parser.add_argument('--samlsessions-dburi',
+                        help='SAML 2 sessions database URI (override ' +
+                             'template)')
+    parser.add_argument('--cleanup-interval', default=30,
+                        help='Interval between cleaning up stale database ' +
+                             'entries (in minutes, default: 30 minutes)')
 
     lms = []
 
@@ -400,7 +430,7 @@ def parse_args(plugins):
     else:
         args['lm_order'] = args['lm_order'].split(',')
 
-    if len(args['lm_order']) == 0:
+    if len(args['lm_order']) == 0 and args['ipa'] != 'yes':
         sys.exit('No login plugins are enabled.')
 
     #FIXME: check instance is only alphanums
@@ -411,12 +441,12 @@ if __name__ == '__main__':
     opts = []
     out = 0
     openlogs()
+    logger.setLevel(logging.DEBUG)
+
     try:
         fplugins = find_plugins()
         opts = parse_args(fplugins)
 
-        logger.setLevel(logging.DEBUG)
-
         logger.debug('Installation arguments:')
         for k in sorted(opts.iterkeys()):
             logger.debug('%s: %s', k, opts[k])
@@ -429,7 +459,9 @@ if __name__ == '__main__':
         else:
             install(fplugins, opts)
     except Exception, e:  # pylint: disable=broad-except
-        logger.exception(e)
+        logger.info(str(e))         # emit message to console
+        logger.debug(e, exc_info=1) # add backtrace information to logfile
+
         if 'uninstall' in opts and opts['uninstall'] is True:
             logger.info('Uninstallation aborted.')
         else: