Silence cherrypy logging to the screen
[cascardo/ipsilon.git] / ipsilon / install / server.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2014  Simo Sorce <simo@redhat.com>
4 #
5 # see file 'COPYING' for use and warranty information
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 from ipsilon.login.common import LoginMgrsInstall
21 from ipsilon.providers.common import ProvidersInstall
22 import argparse
23 import cherrypy
24 import logging
25 import os
26 import shutil
27 import sys
28 import time
29
30
31 TEMPLATES = '/usr/share/ipsilon/templates/install'
32 CONFDIR = '/etc/ipsilon'
33 HTTPDCONFD = '/etc/httpd/conf.d'
34
35
36 class ConfigurationError(Exception):
37
38     def __init__(self, message):
39         super(ConfigurationError, self).__init__(message)
40         self.message = message
41
42     def __str__(self):
43         return repr(self.message)
44
45
46 #Silence cherrypy logging to screen
47 cherrypy.log.screen = False
48
49 # Regular logging
50 LOGFILE = '/var/log/ipsilon-install.log'
51 logger = logging.getLogger()
52
53
54 def openlogs():
55     global logger  # pylint: disable=W0603
56     if os.path.isfile(LOGFILE):
57         try:
58             created = '%s' % time.ctime(os.path.getctime(LOGFILE))
59             shutil.move(LOGFILE, '%s.%s' % (LOGFILE, created))
60         except IOError:
61             pass
62     logger = logging.getLogger()
63     try:
64         lh = logging.FileHandler(LOGFILE)
65     except IOError, e:
66         print >> sys.stderr, 'Unable to open %s (%s)' % (LOGFILE, str(e))
67         lh = logging.StreamHandler(sys.stderr)
68     formatter = logging.Formatter('[%(asctime)s] %(message)s')
69     lh.setFormatter(formatter)
70     logger.addHandler(lh)
71
72
73 def install(plugins, args):
74     logger.info('Installation initiated')
75     now = time.strftime("%Y%m%d%H%M%S", time.gmtime())
76
77     logger.info('Installing default config files')
78     ipsilon_conf = os.path.join(CONFDIR, 'ipsilon.conf')
79     idp_conf = os.path.join(CONFDIR, 'idp.conf')
80     httpd_conf = os.path.join(HTTPDCONFD, 'idp.conf')
81     if os.path.exists(ipsilon_conf):
82         shutil.move(ipsilon_conf, '%s.bakcup.%s' % (ipsilon_conf, now))
83     if os.path.exists(idp_conf):
84         shutil.move(idp_conf, '%s.backup.%s' % (idp_conf, now))
85     shutil.copy(os.path.join(TEMPLATES, 'ipsilon.conf'), CONFDIR)
86     shutil.copy(os.path.join(TEMPLATES, 'idp.conf'), CONFDIR)
87     if not os.path.exists(httpd_conf):
88         os.symlink(idp_conf, httpd_conf)
89     # Load the cherrypy config from the newly installed file so
90     # that db paths and all is properly set before configuring
91     # components
92     cherrypy.config.update(ipsilon_conf)
93
94     # Move pre-existing admin db away
95     admin_db = cherrypy.config['admin.config.db']
96     if os.path.exists(admin_db):
97         shutil.move(admin_db, '%s.backup.%s' % (admin_db, now))
98
99     logger.info('Configuring login managers')
100     for plugin_name in args['lm_order']:
101         plugin = plugins['Login Managers'][plugin_name]
102         plugin.configure(args)
103
104     logger.info('Configuring Authentication Providers')
105     for plugin_name in plugins['Auth Providers']:
106         plugin = plugins['Auth Providers'][plugin_name]
107         plugin.configure(args)
108
109
110 def uninstall(plugins, args):
111     logger.info('Uninstallation initiated')
112     raise Exception('Not Implemented')
113
114
115 def find_plugins():
116     plugins = {
117         'Login Managers': LoginMgrsInstall().plugins,
118         'Auth Providers': ProvidersInstall().plugins
119     }
120     return plugins
121
122
123 def parse_args(plugins):
124     parser = argparse.ArgumentParser(description='Ipsilon Install Options')
125     parser.add_argument('--version',
126                         action='version', version='%(prog)s 0.1')
127     parser.add_argument('-o', '--login-managers-order', dest='lm_order',
128                         help='Comma separated list of login managers')
129     parser.add_argument('--ipa', choices=['yes', 'no'], default='yes',
130                         help='Detect and use an IPA server for authentication')
131     parser.add_argument('--uninstall', action='store_true',
132                         help="Uninstall the server and all data")
133
134     lms = []
135
136     for plugin_group in plugins:
137         group = parser.add_argument_group(plugin_group)
138         for plugin_name in plugins[plugin_group]:
139             plugin = plugins[plugin_group][plugin_name]
140             if plugin.ptype == 'login':
141                 lms.append(plugin.name)
142             plugin.install_args(group)
143
144     args = vars(parser.parse_args())
145
146     if args['lm_order'] is None:
147         args['lm_order'] = []
148         for name in lms:
149             if args[name] == 'yes':
150                 args['lm_order'].append(name)
151     else:
152         args['lm_order'] = args['lm_order'].split(',')
153
154     if len(args['lm_order']) == 0:
155         #force the basic pam provider if nothing else is selected
156         if 'pam' not in args:
157             parser.print_help()
158             sys.exit(-1)
159         args['lm_order'] = ['pam']
160         args['pam'] = 'yes'
161
162     return args
163
164 if __name__ == '__main__':
165     opts = []
166     out = 0
167     openlogs()
168     try:
169         fplugins = find_plugins()
170         opts = parse_args(fplugins)
171
172         logger.setLevel(logging.DEBUG)
173
174         logger.info('Intallation arguments:')
175         for k in sorted(opts.iterkeys()):
176             logger.info('%s: %s', k, opts[k])
177
178         if 'uninstall' in opts and opts['uninstall'] is True:
179             uninstall(fplugins, opts)
180
181         install(fplugins, opts)
182     except Exception, e:  # pylint: disable=broad-except
183         logger.exception(e)
184         if 'uninstall' in opts and opts['uninstall'] is True:
185             print 'Uninstallation aborted.'
186         else:
187             print 'Installation aborted.'
188         print 'See log file %s for details' % LOGFILE
189         out = 1
190     finally:
191         if out == 0:
192             if 'uninstall' in opts and opts['uninstall'] is True:
193                 print 'Uninstallation complete.'
194             else:
195                 print 'Installation complete.'
196     sys.exit(out)