This replaces the print statements in the installer code with
a python logger so we can log all output to the installer log
and a subset of it to stdout in one step without duplication.
The cherrypy.log.error() logs to the "error" log at a severity
of logging.INFO by default. Set an appropriate log level for
these as well.
https://fedorahosted.org/ipsilon/ticket/35
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-by: Simo Sorce <simo@redhat.com>
15 files changed:
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import cherrypy
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import cherrypy
from ipsilon.util.page import Page
from ipsilon.util.page import admin_protect
from ipsilon.util.endpoint import allow_iframe
from ipsilon.util.page import Page
from ipsilon.util.page import admin_protect
from ipsilon.util.endpoint import allow_iframe
if value != option.get_value():
cherrypy.log.error("Storing [%s]: %s = %s" %
if value != option.get_value():
cherrypy.log.error("Storing [%s]: %s = %s" %
- (self._po.name, name, value))
+ (self._po.name, name, value),
+ severity=logging.DEBUG)
option.set_value(value)
new_db_values[name] = option.export_value()
option.set_value(value)
new_db_values[name] = option.export_value()
return
for plugin in self._site[facility].available:
return
for plugin in self._site[facility].available:
- cherrypy.log.error('Admin info plugin: %s' % plugin)
+ cherrypy.log.error('Admin info plugin: %s' % plugin,
+ severity=logging.DEBUG)
obj = self._site[facility].available[plugin]
page = AdminPluginConfig(obj, self._site, self)
if hasattr(obj, 'admin'):
obj = self._site[facility].available[plugin]
page = AdminPluginConfig(obj, self._site, self)
if hasattr(obj, 'admin'):
import os
import socket
import subprocess
import os
import socket
import subprocess
from ipsilon.helpers.common import EnvHelpersInstaller
from ipsilon.helpers.common import EnvHelpersInstaller
# Check if we already have a keytab for HTTP
if 'gssapi_httpd_keytab' in opts:
msg = "Searching for keytab in: %s" % opts['gssapi_httpd_keytab']
# Check if we already have a keytab for HTTP
if 'gssapi_httpd_keytab' in opts:
msg = "Searching for keytab in: %s" % opts['gssapi_httpd_keytab']
- print >> sys.stdout, msg,
if os.path.exists(opts['gssapi_httpd_keytab']):
if os.path.exists(opts['gssapi_httpd_keytab']):
- print >> sys.stdout, "... Found!"
+ logger.info(msg + "... Found!")
- print >> sys.stdout, "... Not found!"
+ logger.info(msg + "... Not found!")
msg = "Searching for keytab in: %s" % HTTPD_IPA_KEYTAB
msg = "Searching for keytab in: %s" % HTTPD_IPA_KEYTAB
- print >> sys.stdout, msg,
if os.path.exists(HTTPD_IPA_KEYTAB):
opts['gssapi_httpd_keytab'] = HTTPD_IPA_KEYTAB
if os.path.exists(HTTPD_IPA_KEYTAB):
opts['gssapi_httpd_keytab'] = HTTPD_IPA_KEYTAB
- print >> sys.stdout, "... Found!"
+ logger.info(msg + "... Found!")
- print >> sys.stdout, "... Not found!"
+ logger.info(msg + "... Not found!")
us = socket.gethostname()
princ = 'HTTP/%s@%s' % (us, self.realm)
us = socket.gethostname()
princ = 'HTTP/%s@%s' % (us, self.realm)
api.Backend.rpcclient.connect()
logger.debug('Try RPC connection')
api.Backend.rpcclient.forward('ping')
api.Backend.rpcclient.connect()
logger.debug('Try RPC connection')
api.Backend.rpcclient.forward('ping')
- print >> sys.stdout, "... Succeeded!"
+ logger.debug("... Succeeded!")
except ipaerrors.KerberosError as e:
except ipaerrors.KerberosError as e:
- print >> sys.stderr, NO_CREDS_FOR_KEYTAB
logger.error('Invalid credentials: [%s]', repr(e))
if api.Backend.rpcclient.isconnected():
api.Backend.rpcclient.disconnect()
raise Exception('Invalid credentials: [%s]' % e)
except ipaerrors.PublicError as e:
logger.error('Invalid credentials: [%s]', repr(e))
if api.Backend.rpcclient.isconnected():
api.Backend.rpcclient.disconnect()
raise Exception('Invalid credentials: [%s]' % e)
except ipaerrors.PublicError as e:
- print >> sys.stderr, "Can't connect to any IPA server"
logger.error(
'Cannot connect to the server due to generic error: %s', e)
if api.Backend.rpcclient.isconnected():
logger.error(
'Cannot connect to the server due to generic error: %s', e)
if api.Backend.rpcclient.isconnected():
except ipaerrors.DuplicateEntry:
logger.debug('Principal %s already exists', princ)
except ipaerrors.NotFound as e:
except ipaerrors.DuplicateEntry:
logger.debug('Principal %s already exists', princ)
except ipaerrors.NotFound as e:
- print >> sys.stderr, "%s" % e
logger.error('%s', e)
raise Exception('%s' % e)
except ipaerrors.ACIError as e:
logger.error('%s', e)
raise Exception('%s' % e)
except ipaerrors.ACIError as e:
- print >> sys.stderr, NO_CREDS_FOR_KEYTAB
- logger.error('Invalid credentials: [%s]', repr(e))
+ logger.error(NO_CREDS_FOR_KEYTAB)
+ logger.debug('Invalid credentials: [%s]', repr(e))
raise Exception('Invalid credentials: [%s]' % e)
finally:
server = api.Backend.rpcclient.api.env.server
raise Exception('Invalid credentials: [%s]' % e)
finally:
server = api.Backend.rpcclient.api.env.server
try:
msg = "Trying to fetch keytab[%s] for %s" % (
opts['gssapi_httpd_keytab'], princ)
try:
msg = "Trying to fetch keytab[%s] for %s" % (
opts['gssapi_httpd_keytab'], princ)
- print >> sys.stdout, msg,
subprocess.check_output([IPA_GETKEYTAB,
'-s', server, '-p', princ,
'-k', opts['gssapi_httpd_keytab']],
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError, e:
# unfortunately this one is fatal
subprocess.check_output([IPA_GETKEYTAB,
'-s', server, '-p', princ,
'-k', opts['gssapi_httpd_keytab']],
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError, e:
# unfortunately this one is fatal
- print >> sys.stderr, FAILED_TO_GET_KEYTAB
+ logger.error(FAILED_TO_GET_KEYTAB)
logger.info('Error trying to get HTTP keytab:')
logger.info('Cmd> %s\n%s', e.cmd, e.output)
raise Exception('Missing keytab: [%s]' % e)
logger.info('Error trying to get HTTP keytab:')
logger.info('Cmd> %s\n%s', e.cmd, e.output)
raise Exception('Missing keytab: [%s]' % e)
import time
import subprocess
import SSSDConfig
import time
import subprocess
import SSSDConfig
SSSD_CONF = '/etc/sssd/sssd.conf'
SSSD_CONF = '/etc/sssd/sssd.conf'
except Exception as e: # pylint: disable=broad-except
# Unable to read existing SSSD config so it is probably not
# configured.
except Exception as e: # pylint: disable=broad-except
# Unable to read existing SSSD config so it is probably not
# configured.
- print 'Loading SSSD config failed: %s' % e
+ logging.info('Loading SSSD config failed: %s', e)
return False
if not opts['info_sssd_domain']:
return False
if not opts['info_sssd_domain']:
try:
sssd_domain = sssdconfig.get_domain(domain)
except SSSDConfig.NoDomainError:
try:
sssd_domain = sssdconfig.get_domain(domain)
except SSSDConfig.NoDomainError:
- print 'No SSSD domain %s' % domain
+ logging.info('No SSSD domain %s', domain)
continue
else:
sssd_domain.set_option(
continue
else:
sssd_domain.set_option(
)
sssdconfig.save_domain(sssd_domain)
configured += 1
)
sssdconfig.save_domain(sssd_domain)
configured += 1
- print "Configured SSSD domain %s" % domain
+ logging.info("Configured SSSD domain %s", domain)
- print 'No SSSD domains configured'
+ logging.info('No SSSD domains configured')
except Exception, e: # pylint: disable=broad-except
log_exception(e)
if 'uninstall' in args and args['uninstall'] is True:
except Exception, e: # pylint: disable=broad-except
log_exception(e)
if 'uninstall' in args and args['uninstall'] is True:
- print 'Uninstallation aborted.'
+ logging.info('Uninstallation aborted.')
- print 'Installation aborted.'
+ logging.info('Installation aborted.')
out = 1
finally:
if out == 0:
if 'uninstall' in args and args['uninstall'] is True:
out = 1
finally:
if out == 0:
if 'uninstall' in args and args['uninstall'] is True:
- print 'Uninstallation complete.'
+ logging.info('Uninstallation complete.')
- print 'Installation complete.'
+ logging.info('Installation complete.')
lh = logging.StreamHandler(sys.stderr)
formatter = logging.Formatter('[%(asctime)s] %(message)s')
lh.setFormatter(formatter)
lh = logging.StreamHandler(sys.stderr)
formatter = logging.Formatter('[%(asctime)s] %(message)s')
lh.setFormatter(formatter)
+ lh.setLevel(logging.DEBUG)
+ logger.propagate = False
+ ch = logging.StreamHandler(sys.stdout)
+ formatter = logging.Formatter('%(message)s')
+ ch.setFormatter(formatter)
+ ch.setLevel(logging.INFO)
+ logger.addHandler(ch)
+ cherrypy.log.error_log.setLevel(logging.DEBUG)
def install(plugins, args):
def install(plugins, args):
for plugin_name in plugins['Environment Helpers']:
plugin = plugins['Environment Helpers'][plugin_name]
if plugin.configure_server(args) == False:
for plugin_name in plugins['Environment Helpers']:
plugin = plugins['Environment Helpers'][plugin_name]
if plugin.configure_server(args) == False:
- print 'Configuration of environment helper %s failed' % plugin_name
+ logger.info('Configuration of environment helper %s failed' % plugin_name)
logger.info('Configuring login managers')
for plugin_name in args['lm_order']:
logger.info('Configuring login managers')
for plugin_name in args['lm_order']:
except KeyError:
sys.exit('Login provider %s not installed' % plugin_name)
if plugin.configure(args) == False:
except KeyError:
sys.exit('Login provider %s not installed' % plugin_name)
if plugin.configure(args) == False:
- print 'Configuration of login manager %s failed' % plugin_name
+ logger.info('Configuration of login manager %s failed' % plugin_name)
logger.info('Configuring Info provider')
for plugin_name in plugins['Info Provider']:
plugin = plugins['Info Provider'][plugin_name]
if plugin.configure(args) == False:
logger.info('Configuring Info provider')
for plugin_name in plugins['Info Provider']:
plugin = plugins['Info Provider'][plugin_name]
if plugin.configure(args) == False:
- print 'Configuration of info provider %s failed' % plugin_name
+ logger.info('Configuration of info provider %s failed' % plugin_name)
logger.info('Configuring Authentication Providers')
for plugin_name in plugins['Auth Providers']:
plugin = plugins['Auth Providers'][plugin_name]
if plugin.configure(args) == False:
logger.info('Configuring Authentication Providers')
for plugin_name in plugins['Auth Providers']:
plugin = plugins['Auth Providers'][plugin_name]
if plugin.configure(args) == False:
- print 'Configuration of auth provider %s failed' % plugin_name
+ logger.info('Configuration of auth provider %s failed' % plugin_name)
# Fixup permissions so only the ipsilon user can read these files
files.fix_user_dirs(instance_conf, opts['system_user'])
# Fixup permissions so only the ipsilon user can read these files
files.fix_user_dirs(instance_conf, opts['system_user'])
for plugin_name in plugins['Environment Helpers']:
plugin = plugins['Environment Helpers'][plugin_name]
if plugin.unconfigure(args) == False:
for plugin_name in plugins['Environment Helpers']:
plugin = plugins['Environment Helpers'][plugin_name]
if plugin.unconfigure(args) == False:
- print 'Removal of environment helper %s failed' % plugin_name
+ logger.info('Removal of environment helper %s failed' % plugin_name)
logger.info('Removing login managers')
for plugin_name in plugins['Login Managers']:
plugin = plugins['Login Managers'][plugin_name]
if plugin.unconfigure(args) == False:
logger.info('Removing login managers')
for plugin_name in plugins['Login Managers']:
plugin = plugins['Login Managers'][plugin_name]
if plugin.unconfigure(args) == False:
- print 'Removal of login manager %s failed' % plugin_name
+ logger.info('Removal of login manager %s failed' % plugin_name)
logger.info('Removing Info providers')
for plugin_name in plugins['Info Provider']:
plugin = plugins['Info Provider'][plugin_name]
if plugin.unconfigure(args) == False:
logger.info('Removing Info providers')
for plugin_name in plugins['Info Provider']:
plugin = plugins['Info Provider'][plugin_name]
if plugin.unconfigure(args) == False:
- print 'Removal of info provider %s failed' % plugin_name
+ logger.info('Removal of info provider %s failed' % plugin_name)
logger.info('Removing Authentication Providers')
for plugin_name in plugins['Auth Providers']:
plugin = plugins['Auth Providers'][plugin_name]
if plugin.unconfigure(args) == False:
logger.info('Removing Authentication Providers')
for plugin_name in plugins['Auth Providers']:
plugin = plugins['Auth Providers'][plugin_name]
if plugin.unconfigure(args) == False:
- print 'Removal of auth provider %s failed' % plugin_name
+ logger.info('Removal of auth provider %s failed' % plugin_name)
logger.info('Removing httpd configuration')
os.remove(httpd_conf)
logger.info('Removing httpd configuration')
os.remove(httpd_conf)
logger.setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG)
- logger.info('Intallation arguments:')
+ logger.debug('Installation arguments:')
for k in sorted(opts.iterkeys()):
for k in sorted(opts.iterkeys()):
- logger.info('%s: %s', k, opts[k])
+ logger.debug('%s: %s', k, opts[k])
if 'uninstall' in opts and opts['uninstall'] is True:
if not os.path.exists(os.path.join(CONFDIR, opts['instance'])):
if 'uninstall' in opts and opts['uninstall'] is True:
if not os.path.exists(os.path.join(CONFDIR, opts['instance'])):
- print 'Instance %s could not be found' % opts['instance']
+ logger.info('Instance %s could not be found' % opts['instance'])
sys.exit(0)
uninstall(fplugins, opts)
else:
sys.exit(0)
uninstall(fplugins, opts)
else:
except Exception, e: # pylint: disable=broad-except
logger.exception(e)
if 'uninstall' in opts and opts['uninstall'] is True:
except Exception, e: # pylint: disable=broad-except
logger.exception(e)
if 'uninstall' in opts and opts['uninstall'] is True:
- print 'Uninstallation aborted.'
+ logger.info('Uninstallation aborted.')
- print 'Installation aborted.'
- print 'See log file %s for details' % LOGFILE
+ logger.info('Installation aborted.')
+ logger.info('See log file %s for details' % LOGFILE)
out = 1
except SystemExit:
out = 1
out = 1
except SystemExit:
out = 1
finally:
if out == 0:
if 'uninstall' in opts and opts['uninstall'] is True:
finally:
if out == 0:
if 'uninstall' in opts and opts['uninstall'] is True:
- print 'Uninstallation complete.'
+ logger.info('Uninstallation complete.')
- print 'Installation complete.'
- print 'Please restart HTTPD to enable the IdP instance.'
+ logger.info('Installation complete.')
+ logger.info('Please restart HTTPD to enable the IdP instance.')
from ipsilon.util.policy import Policy
from ipsilon.util import config as pconfig
import cherrypy
from ipsilon.util.policy import Policy
from ipsilon.util import config as pconfig
import cherrypy
from fedora.client.fasproxy import FasProxyClient
from fedora.client import AuthError
from fedora.client.fasproxy import FasProxyClient
from fedora.client import AuthError
try:
_, data = self.lm.fpc.login(username, password)
except AuthError, e:
try:
_, data = self.lm.fpc.login(username, password)
except AuthError, e:
- cherrypy.log.error("Authentication error [%s]" % str(e))
+ cherrypy.log.error("Authentication error [%s]" % str(e),
+ severity=logging.ERROR)
except Exception, e: # pylint: disable=broad-except
except Exception, e: # pylint: disable=broad-except
- cherrypy.log.error("Unknown Error [%s]" % str(e))
+ cherrypy.log.error("Unknown Error [%s]" % str(e),
+ severity=logging.ERROR)
+
if data and data.user:
userdata = self.make_userdata(data.user)
return self.lm.auth_successful(self.trans,
if data and data.user:
userdata = self.make_userdata(data.user)
return self.lm.auth_successful(self.trans,
userdata=userdata)
else:
error = "Authentication failed"
userdata=userdata)
else:
error = "Authentication failed"
- cherrypy.log.error(error)
+ cherrypy.log.error(error, severity=logging.ERROR)
else:
error = "Username or password is missing"
else:
error = "Username or password is missing"
- cherrypy.log.error("Error: " + error)
+ cherrypy.log.error("Error: " + error, severity=logging.ERROR)
context = self.create_tmpl_context(
username=username,
context = self.create_tmpl_context(
username=username,
from string import Template
import cherrypy
import subprocess
from string import Template
import cherrypy
import subprocess
class Form(LoginFormBase):
class Form(LoginFormBase):
error = cherrypy.request.headers['EXTERNAL_AUTH_ERROR']
except KeyError:
error = "Unknown error using external authentication"
error = cherrypy.request.headers['EXTERNAL_AUTH_ERROR']
except KeyError:
error = "Unknown error using external authentication"
- cherrypy.log.error("Error: %s" % error)
+ cherrypy.log.error("Error: %s" % error, logging.ERROR)
return self.lm.auth_failed(self.trans)
return self.lm.auth_failed(self.trans)
from string import Template
import cherrypy
import os
from string import Template
import cherrypy
import os
class GSSAPI(LoginPageBase):
class GSSAPI(LoginPageBase):
class GSSAPIError(LoginPageBase):
def root(self, *args, **kwargs):
class GSSAPIError(LoginPageBase):
def root(self, *args, **kwargs):
- cherrypy.log.error('REQUEST: %s' % cherrypy.request.headers)
+ cherrypy.log.error('REQUEST: %s' % cherrypy.request.headers,
+ severity=logging.DEBUG)
# If we have no negotiate header return whatever mod_auth_gssapi
# generated and wait for the next request
# If we have no negotiate header return whatever mod_auth_gssapi
# generated and wait for the next request
from ipsilon.util.plugin import PluginObject
from ipsilon.util import config as pconfig
import cherrypy
from ipsilon.util.plugin import PluginObject
from ipsilon.util import config as pconfig
import cherrypy
class TestAuth(LoginFormBase):
class TestAuth(LoginFormBase):
error = "Authentication failed"
else:
error = "Username or password is missing"
error = "Authentication failed"
else:
error = "Username or password is missing"
- cherrypy.log.error("Error: " + error)
+ cherrypy.log.error("Error: " + error, severity=logging.ERROR)
context = self.create_tmpl_context(
username=username,
context = self.create_tmpl_context(
username=username,
if opts['testauth'] != 'yes':
return
if opts['testauth'] != 'yes':
return
+ logging.debug(self.pargs)
# Add configuration data to database
po = PluginObject(*self.pargs)
po.name = 'testauth'
# Add configuration data to database
po = PluginObject(*self.pargs)
po.name = 'testauth'
from ipsilon.providers.saml2.provider import InvalidProviderId
from copy import deepcopy
import requests
from ipsilon.providers.saml2.provider import InvalidProviderId
from copy import deepcopy
import requests
class NewSPAdminPage(AdminPage):
class NewSPAdminPage(AdminPage):
set(value) == set(option.get_value())):
continue
cherrypy.log.error("Storing %s = %s" %
set(value) == set(option.get_value())):
continue
cherrypy.log.error("Storing %s = %s" %
+ (name, value), severity=logging.DEBUG)
new_db_values[name] = value
if len(new_db_values) != 0:
new_db_values[name] = value
if len(new_db_values) != 0:
import cherrypy
import json
import cherrypy
import json
from functools import wraps
from ipsilon.util.endpoint import Endpoint
from functools import wraps
from ipsilon.util.endpoint import Endpoint
for plugin in self._site[facility].available:
obj = self._site[facility].available[plugin]
if hasattr(obj, 'rest'):
for plugin in self._site[facility].available:
obj = self._site[facility].available[plugin]
if hasattr(obj, 'rest'):
- cherrypy.log.error('Rest plugin: %s' % plugin)
+ cherrypy.log.error('Rest plugin: %s' % plugin,
+ severity=logging.DEBUG)
obj.rest.mount(self)
def root_with_msg(self, message=None, message_type=None, changed=None):
obj.rest.mount(self)
def root_with_msg(self, message=None, message_type=None, changed=None):
import ConfigParser
import os
import uuid
import ConfigParser
import os
import uuid
OPTIONS_COLUMNS = ['name', 'option', 'value']
OPTIONS_COLUMNS = ['name', 'option', 'value']
@classmethod
def get_connection(cls, name):
if name not in cls.__instances.keys():
@classmethod
def get_connection(cls, name):
if name not in cls.__instances.keys():
- print 'SqlStore new: %s' % name
+ logging.debug('SqlStore new: %s', name)
cls.__instances[name] = SqlStore(name)
return cls.__instances[name]
cls.__instances[name] = SqlStore(name)
return cls.__instances[name]
import inspect
import os
import traceback
import inspect
import os
import traceback
def log_request_response():
def log_request_response():
cherrypy.log(fact)
def error(self, fact):
cherrypy.log(fact)
def error(self, fact):
- cherrypy.log.error('ERROR: %s' % fact)
+ cherrypy.log.error('ERROR: %s' % fact, severity=logging.ERROR)
if cherrypy.config.get('stacktrace_on_error', False):
cherrypy.log.error(Log.stacktrace())
if cherrypy.config.get('stacktrace_on_error', False):
cherrypy.log.error(Log.stacktrace())
import imp
import cherrypy
import inspect
import imp
import cherrypy
import inspect
from ipsilon.util.data import AdminStore
from ipsilon.util.log import Log
from ipsilon.util.data import AdminStore
from ipsilon.util.log import Log
def _load_class(self, tree, class_type, file_name, *pargs):
cherrypy.log.error('Check module %s for class %s' % (file_name,
def _load_class(self, tree, class_type, file_name, *pargs):
cherrypy.log.error('Check module %s for class %s' % (file_name,
+ class_type), severity=logging.DEBUG)
name, ext = os.path.splitext(os.path.split(file_name)[-1])
try:
if ext.lower() == '.py':
name, ext = os.path.splitext(os.path.split(file_name)[-1])
try:
if ext.lower() == '.py':
else:
return
except Exception, e: # pylint: disable=broad-except
else:
return
except Exception, e: # pylint: disable=broad-except
- cherrypy.log.error('Failed to load "%s" module: [%s]' % (name, e))
+ cherrypy.log.error('Failed to load "%s" module: [%s]' % (name, e),
+ severity=logging.ERROR)
return
if hasattr(mod, class_type):
instance = getattr(mod, class_type)(*pargs)
public_name = getattr(instance, 'name', name)
tree[public_name] = instance
return
if hasattr(mod, class_type):
instance = getattr(mod, class_type)(*pargs)
public_name = getattr(instance, 'name', name)
tree[public_name] = instance
- cherrypy.log.error('Added module %s as %s' % (name, public_name))
+ cherrypy.log.error('Added module %s as %s' % (name, public_name),
+ severity=logging.DEBUG)
def _load_classes(self, tree, path, class_type, *pargs):
files = None
try:
files = os.listdir(path)
except Exception, e: # pylint: disable=broad-except
def _load_classes(self, tree, path, class_type, *pargs):
files = None
try:
files = os.listdir(path)
except Exception, e: # pylint: disable=broad-except
- cherrypy.log.error('No modules in %s: [%s]' % (path, e))
+ cherrypy.log.error('No modules in %s: [%s]' % (path, e),
+ severity=logging.ERROR)
return
for name in files:
return
for name in files:
from ipsilon.util.data import UserStore
from ipsilon.util.log import Log
import cherrypy
from ipsilon.util.data import UserStore
from ipsilon.util.log import Log
import cherrypy
if not type(user) is User:
raise TypeError
# Completely reset user data
if not type(user) is User:
raise TypeError
# Completely reset user data
- cherrypy.log.error('%s %s' % (user.name, user.fullname))
+ cherrypy.log.error('%s %s' % (user.name, user.fullname),
+ severity=logging.INFO)
user.reset()
# Destroy current session in all cases
user.reset()
# Destroy current session in all cases