mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
[enh] Be more verbose in modules using new logging facilities
This commit is contained in:
parent
c93ecbd900
commit
1b0aa97cd7
8 changed files with 178 additions and 82 deletions
|
@ -7,6 +7,7 @@
|
|||
"permission_denied" : "Permission denied",
|
||||
"root_required" : "You must be root to perform this action",
|
||||
"instance_already_running" : "An instance is already running",
|
||||
"error_see_log" : "An error occured. Please see the log for details.",
|
||||
|
||||
"unable_authenticate" : "Unable to authenticate",
|
||||
"unable_retrieve_session" : "Unable to retrieve the session",
|
||||
|
@ -16,6 +17,7 @@
|
|||
|
||||
"argument_required" : "Argument {:s} is required",
|
||||
"invalid_argument": "Invalid argument '{:s}': {:s}",
|
||||
"pattern_not_match": "Does not match pattern",
|
||||
"password" : "Password",
|
||||
"invalid_password" : "Invalid password",
|
||||
"confirm" : "Confirm {:s}",
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"permission_denied": "Permission refusée",
|
||||
"root_required": "Vous devez avoir les droits super-utilisateur pour exécuter cette action",
|
||||
"instance_already_running": "Une instance est déjà en cours d'exécution",
|
||||
"error_see_log" : "Une erreur est survenue. Veuillez consulter les journaux pour plus de détails.",
|
||||
"unable_authenticate": "Impossible de vous authentifier",
|
||||
"unable_retrieve_session": "Impossible de récupérer la session",
|
||||
"ldap_server_down": "Impossible d'atteindre le serveur LDAP",
|
||||
|
@ -13,6 +14,7 @@
|
|||
"ldap_attribute_already_exists": "L'attribut existe déjà : '{:s}={:s}'",
|
||||
"argument_required": "L'argument {:s} est requis",
|
||||
"invalid_argument": "Argument '{:s}' incorrect : {:s}",
|
||||
"pattern_not_match": "Ne correspond pas au motif",
|
||||
"password": "Mot de passe",
|
||||
"invalid_password": "Mot de passe incorrect",
|
||||
"confirm": "Confirmez le {:s}",
|
||||
|
@ -26,4 +28,4 @@
|
|||
"not_logged_in": "Vous n'êtes pas connecté",
|
||||
"server_already_running": "Un server est déjà en cours d'exécution sur ce port",
|
||||
"websocket_request_expected": "Excepter une demande de WebSocket"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,6 @@ class AskParameter(_ExtraParameter):
|
|||
skipped_iface = [ 'api' ]
|
||||
|
||||
def __call__(self, message, arg_name, arg_value):
|
||||
# TODO: Fix asked arguments ordering
|
||||
if arg_value:
|
||||
return arg_value
|
||||
|
||||
|
@ -106,14 +105,14 @@ class AskParameter(_ExtraParameter):
|
|||
|
||||
@classmethod
|
||||
def validate(klass, value, arg_name):
|
||||
# Allow boolean or empty string
|
||||
# Deprecated boolean or empty string
|
||||
if isinstance(value, bool) or (isinstance(value, str) and not value):
|
||||
logging.debug("value of '%s' extra parameter for '%s' argument should be a string" \
|
||||
% (klass.name, arg_name))
|
||||
logger.warning("expecting a string for extra parameter '%s' of " \
|
||||
"argument '%s'", klass.name, arg_name)
|
||||
value = arg_name
|
||||
elif not isinstance(value, str):
|
||||
raise TypeError("Invalid type of '%s' extra parameter for '%s' argument" \
|
||||
% (klass.name, arg_name))
|
||||
raise TypeError("parameter value must be a string, got %r" \
|
||||
% value)
|
||||
return value
|
||||
|
||||
class PasswordParameter(AskParameter):
|
||||
|
@ -156,18 +155,28 @@ class PatternParameter(_ExtraParameter):
|
|||
v = arg_value
|
||||
|
||||
if v and not re.match(pattern, v or '', re.UNICODE):
|
||||
logger.debug("argument value '%s' for '%s' doesn't match pattern '%s'",
|
||||
v, arg_name, pattern)
|
||||
|
||||
# Attempt to retrieve message translation
|
||||
msg = m18n.n(message)
|
||||
if msg == message:
|
||||
msg = m18n.g(message)
|
||||
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('invalid_argument',
|
||||
arg_name, m18n.n(message)))
|
||||
arg_name, msg))
|
||||
return arg_value
|
||||
|
||||
@staticmethod
|
||||
def validate(value, arg_name):
|
||||
# Tolerate string type
|
||||
# Deprecated string type
|
||||
if isinstance(value, str):
|
||||
logging.warning("value of 'pattern' extra parameter for '%s' argument should be a list" % arg_name)
|
||||
value = [value, _("'%s' argument is not matching the pattern") % arg_name]
|
||||
logger.warning("expecting a list for extra parameter 'pattern' of " \
|
||||
"argument '%s'", arg_name)
|
||||
value = [value, 'pattern_not_match']
|
||||
elif not isinstance(value, list) or len(value) != 2:
|
||||
raise TypeError("Invalid type of 'pattern' extra parameter for '%s' argument" % arg_name)
|
||||
raise TypeError("parameter value must be a list, got %r" \
|
||||
% value)
|
||||
return value
|
||||
|
||||
class RequiredParameter(_ExtraParameter):
|
||||
|
@ -181,6 +190,8 @@ class RequiredParameter(_ExtraParameter):
|
|||
|
||||
def __call__(self, required, arg_name, arg_value):
|
||||
if required and (arg_value is None or arg_value == ''):
|
||||
logger.debug("argument '%s' is required",
|
||||
v, arg_name, pattern)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('argument_required',
|
||||
arg_name))
|
||||
return arg_value
|
||||
|
@ -188,7 +199,8 @@ class RequiredParameter(_ExtraParameter):
|
|||
@staticmethod
|
||||
def validate(value, arg_name):
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError("Invalid type of 'required' extra parameter for '%s' argument" % arg_name)
|
||||
raise TypeError("parameter value must be a list, got %r" \
|
||||
% value)
|
||||
return value
|
||||
|
||||
"""
|
||||
|
@ -219,6 +231,7 @@ class ExtraArgumentParser(object):
|
|||
if iface in klass.skipped_iface:
|
||||
continue
|
||||
self.extra[klass.name] = klass
|
||||
logger.debug('extra parameter classes loaded: %s', self.extra.keys())
|
||||
|
||||
def validate(self, arg_name, parameters):
|
||||
"""
|
||||
|
@ -236,8 +249,13 @@ class ExtraArgumentParser(object):
|
|||
# Remove unknown parameters
|
||||
del parameters[p]
|
||||
else:
|
||||
# Validate parameter value
|
||||
parameters[p] = klass.validate(v, arg_name)
|
||||
try:
|
||||
# Validate parameter value
|
||||
parameters[p] = klass.validate(v, arg_name)
|
||||
except Exception as e:
|
||||
logger.error("unable to validate extra parameter '%s' " \
|
||||
"for argument '%s': %s", p, arg_name, e)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
|
||||
return parameters
|
||||
|
||||
|
@ -332,12 +350,10 @@ class ActionsMap(object):
|
|||
|
||||
"""
|
||||
def __init__(self, parser, namespaces=[], use_cache=True):
|
||||
self.use_cache = use_cache
|
||||
if not issubclass(parser, BaseActionsMapParser):
|
||||
raise ValueError("Invalid parser class '%s'" % parser.__name__)
|
||||
self._parser_class = parser
|
||||
|
||||
logging.debug("initializing ActionsMap for the interface '%s'" % parser.interface)
|
||||
self.use_cache = use_cache
|
||||
|
||||
if len(namespaces) == 0:
|
||||
namespaces = self.get_namespaces()
|
||||
|
@ -345,7 +361,7 @@ class ActionsMap(object):
|
|||
|
||||
# Iterate over actions map namespaces
|
||||
for n in namespaces:
|
||||
logging.debug("loading '%s' actions map namespace" % n)
|
||||
logger.debug("loading actions map namespace '%s'", n)
|
||||
|
||||
if use_cache:
|
||||
try:
|
||||
|
@ -424,12 +440,18 @@ class ActionsMap(object):
|
|||
fromlist=[func_name])
|
||||
func = getattr(mod, func_name)
|
||||
except (AttributeError, ImportError):
|
||||
raise ImportError("Unable to load function %s.%s/%s"
|
||||
% (namespace, category, func_name))
|
||||
logger.exception("unable to load function %s.%s.%s",
|
||||
namespace, category, func_name)
|
||||
raise MoulinetteError(errno.EIO, m18n.g('error_see_log'))
|
||||
else:
|
||||
log_id = start_action_logging()
|
||||
logger.info('processing action [%s]: %s.%s.%s with args=%s',
|
||||
log_id, namespace, category, action, arguments)
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
# Log arguments in debug mode only for safety reasons
|
||||
logger.info('processing action [%s]: %s.%s.%s with args=%s',
|
||||
log_id, namespace, category, action, arguments)
|
||||
else:
|
||||
logger.info('processing action [%s]: %s.%s.%s',
|
||||
log_id, namespace, category, action)
|
||||
|
||||
# Load translation and process the action
|
||||
m18n.load_namespace(namespace)
|
||||
|
@ -475,7 +497,7 @@ class ActionsMap(object):
|
|||
|
||||
# Iterate over actions map namespaces
|
||||
for n in namespaces:
|
||||
logging.debug("generating cache for '%s' actions map namespace" % n)
|
||||
logger.debug("generating cache for actions map namespace '%s'", n)
|
||||
|
||||
# Read actions map from yaml file
|
||||
am_file = '%s/actionsmap/%s.yml' % (pkg.datadir, n)
|
||||
|
@ -558,7 +580,8 @@ class ActionsMap(object):
|
|||
actions = cp.pop('actions')
|
||||
except KeyError:
|
||||
# Invalid category without actions
|
||||
logging.warning("no actions found in category '%s'" % cn)
|
||||
logger.warning("no actions found in category '%s' in " \
|
||||
"namespace '%s'", cn, n)
|
||||
continue
|
||||
|
||||
# Get category parser
|
||||
|
@ -582,7 +605,8 @@ class ActionsMap(object):
|
|||
# No parser for the action
|
||||
continue
|
||||
except ValueError as e:
|
||||
logging.warning("cannot add action (%s, %s, %s): %s" % (n, cn, an, e))
|
||||
logger.warning("cannot add action (%s, %s, %s): %s",
|
||||
n, cn, an, e)
|
||||
continue
|
||||
else:
|
||||
# Store action identifier and add arguments
|
||||
|
|
|
@ -6,6 +6,9 @@ import logging
|
|||
|
||||
from moulinette.core import MoulinetteError
|
||||
|
||||
logger = logging.getLogger('moulinette.authenticator')
|
||||
|
||||
|
||||
# Base Class -----------------------------------------------------------
|
||||
|
||||
class BaseAuthenticator(object):
|
||||
|
@ -92,11 +95,12 @@ class BaseAuthenticator(object):
|
|||
# Extract id and hash from token
|
||||
s_id, s_hash = token
|
||||
except TypeError:
|
||||
if not password:
|
||||
raise ValueError("Invalid token format")
|
||||
else:
|
||||
# TODO: Log error
|
||||
store_session = False
|
||||
logger.error("unable to extract token parts from '%s'", token)
|
||||
if password is None:
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
|
||||
logger.info("session will not be stored")
|
||||
store_session = False
|
||||
else:
|
||||
if password is None:
|
||||
# Retrieve session
|
||||
|
@ -107,14 +111,19 @@ class BaseAuthenticator(object):
|
|||
self.authenticate(password)
|
||||
except MoulinetteError:
|
||||
raise
|
||||
except Exception as e:
|
||||
logging.error("authentication (name: '%s', type: '%s') fails: %s" \
|
||||
% (self.name, self.vendor, e))
|
||||
except:
|
||||
logger.exception("authentication (name: '%s', vendor: '%s') fails",
|
||||
self.name, self.vendor)
|
||||
raise MoulinetteError(errno.EACCES, m18n.g('unable_authenticate'))
|
||||
|
||||
# Store session
|
||||
if store_session:
|
||||
self._store_session(s_id, s_hash, password)
|
||||
try:
|
||||
self._store_session(s_id, s_hash, password)
|
||||
except:
|
||||
logger.exception("unable to store session")
|
||||
else:
|
||||
logger.debug("session has been stored")
|
||||
|
||||
return self
|
||||
|
||||
|
@ -140,6 +149,7 @@ class BaseAuthenticator(object):
|
|||
with self._open_sessionfile(session_id, 'r') as f:
|
||||
enc_pwd = f.read()
|
||||
except IOError:
|
||||
logger.debug("unable to retrieve session", exc_info=1)
|
||||
raise MoulinetteError(errno.ENOENT,
|
||||
m18r.g('unable_retrieve_session'))
|
||||
else:
|
||||
|
@ -148,7 +158,8 @@ class BaseAuthenticator(object):
|
|||
|
||||
decrypted = gpg.decrypt(enc_pwd, passphrase=session_hash)
|
||||
if decrypted.ok != True:
|
||||
# TODO: Log decrypted.status
|
||||
logger.error("unable to decrypt password for the session: %s",
|
||||
decrypted.status)
|
||||
raise MoulinetteError(errno.EINVAL,
|
||||
m18r.g('unable_retrieve_session'))
|
||||
return decrypted.data
|
||||
|
|
|
@ -3,12 +3,16 @@
|
|||
# TODO: Use Python3 to remove this fix!
|
||||
from __future__ import absolute_import
|
||||
import errno
|
||||
import logging
|
||||
import ldap
|
||||
import ldap.modlist as modlist
|
||||
|
||||
from moulinette.core import MoulinetteError
|
||||
from moulinette.authenticators import BaseAuthenticator
|
||||
|
||||
logger = logging.getLogger('moulinette.authenticator.ldap')
|
||||
|
||||
|
||||
# LDAP Class Implementation --------------------------------------------
|
||||
|
||||
class Authenticator(BaseAuthenticator):
|
||||
|
@ -25,6 +29,8 @@ class Authenticator(BaseAuthenticator):
|
|||
|
||||
"""
|
||||
def __init__(self, name, uri, base_dn, user_rdn=None):
|
||||
logger.debug("initialize authenticator '%s' with: uri='%s', " \
|
||||
"base_dn='%s', user_rdn='%s'", name, uri, base_dn, user_rdn)
|
||||
super(Authenticator, self).__init__(name)
|
||||
|
||||
self.uri = uri
|
||||
|
@ -67,6 +73,7 @@ class Authenticator(BaseAuthenticator):
|
|||
except ldap.INVALID_CREDENTIALS:
|
||||
raise MoulinetteError(errno.EACCES, m18n.g('invalid_password'))
|
||||
except ldap.SERVER_DOWN:
|
||||
logger.exception('unable to reach the server to authenticate')
|
||||
raise MoulinetteError(169, m18n.g('ldap_server_down'))
|
||||
else:
|
||||
self.con = con
|
||||
|
@ -96,6 +103,8 @@ class Authenticator(BaseAuthenticator):
|
|||
try:
|
||||
result = self.con.search_s(base, ldap.SCOPE_SUBTREE, filter, attrs)
|
||||
except:
|
||||
logger.exception("error during LDAP search operation with: base='%s', " \
|
||||
"filter='%s', attrs=%s", base, filter, attrs)
|
||||
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
|
||||
|
||||
result_list = []
|
||||
|
@ -125,6 +134,8 @@ class Authenticator(BaseAuthenticator):
|
|||
try:
|
||||
self.con.add_s(dn, ldif)
|
||||
except:
|
||||
logger.exception("error during LDAP add operation with: rdn='%s', " \
|
||||
"attr_dict=%s", rdn, attr_dict)
|
||||
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
|
||||
else:
|
||||
return True
|
||||
|
@ -144,6 +155,7 @@ class Authenticator(BaseAuthenticator):
|
|||
try:
|
||||
self.con.delete_s(dn)
|
||||
except:
|
||||
logger.exception("error during LDAP delete operation with: rdn='%s'", rdn)
|
||||
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
|
||||
else:
|
||||
return True
|
||||
|
@ -172,6 +184,8 @@ class Authenticator(BaseAuthenticator):
|
|||
|
||||
self.con.modify_ext_s(dn, ldif)
|
||||
except:
|
||||
logger.exception("error during LDAP update operation with: rdn='%s', " \
|
||||
"attr_dict=%s, new_rdn=%s", rdn, attr_dict, new_rdn)
|
||||
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
|
||||
else:
|
||||
return True
|
||||
|
@ -191,6 +205,8 @@ class Authenticator(BaseAuthenticator):
|
|||
if not self.search(filter=attr + '=' + value):
|
||||
continue
|
||||
else:
|
||||
logger.info("attribute '%s' with value '%s' is not unique",
|
||||
attr, value)
|
||||
raise MoulinetteError(errno.EEXIST,
|
||||
m18n.g('ldap_attribute_already_exists',
|
||||
attr, value))
|
||||
|
|
|
@ -9,6 +9,9 @@ import logging
|
|||
|
||||
from importlib import import_module
|
||||
|
||||
logger = logging.getLogger('moulinette.core')
|
||||
|
||||
|
||||
# Package manipulation -------------------------------------------------
|
||||
|
||||
class Package(object):
|
||||
|
@ -25,6 +28,10 @@ class Package(object):
|
|||
def __init__(self, _from_source=False):
|
||||
if _from_source:
|
||||
import sys
|
||||
|
||||
logger.debug('initialize Package object running from source')
|
||||
|
||||
# Retrieve source's base directory
|
||||
basedir = os.path.abspath(os.path.dirname(sys.argv[0]) +'/../')
|
||||
|
||||
# Set local directories
|
||||
|
@ -44,7 +51,8 @@ class Package(object):
|
|||
def __setattr__(self, name, value):
|
||||
if name[0] == '_' and self.__dict__.has_key(name):
|
||||
# Deny reassignation of package directories
|
||||
raise TypeError("cannot reassign constant '%s'")
|
||||
logger.error("cannot reassign Package variable '%s'", name)
|
||||
return
|
||||
self.__dict__[name] = value
|
||||
|
||||
|
||||
|
@ -130,8 +138,8 @@ class Translator(object):
|
|||
|
||||
# Attempt to load default translations
|
||||
if not self._load_translations(default_locale):
|
||||
raise ValueError("Unable to load locale '%s' from '%s'"
|
||||
% (default_locale, locale_dir))
|
||||
logger.error("unable to load locale '%s' from '%s'",
|
||||
default_locale, locale_dir)
|
||||
self.default_locale = default_locale
|
||||
|
||||
def get_locales(self):
|
||||
|
@ -159,8 +167,8 @@ class Translator(object):
|
|||
"""
|
||||
if locale not in self._translations:
|
||||
if not self._load_translations(locale):
|
||||
logging.info("unable to load locale '%s' from '%s'"
|
||||
% (self.default_locale, self.locale_dir))
|
||||
logger.debug("unable to load locale '%s' from '%s'",
|
||||
self.default_locale, self.locale_dir)
|
||||
|
||||
# Revert to default locale
|
||||
self.locale = self.default_locale
|
||||
|
@ -180,18 +188,23 @@ class Translator(object):
|
|||
- key -- The key to translate
|
||||
|
||||
"""
|
||||
def _load_key(locale):
|
||||
value = self._translations[locale][key]
|
||||
return value.encode('utf-8').format(*args, **kwargs)
|
||||
|
||||
try:
|
||||
value = self._translations[self.locale][key]
|
||||
return _load_key(self.locale)
|
||||
except KeyError:
|
||||
try:
|
||||
value = self._translations[self.default_locale][key]
|
||||
logging.info("untranslated key '%s' for locale '%s'" %
|
||||
(key, self.locale))
|
||||
except KeyError:
|
||||
logging.warning("unknown key '%s' for locale '%s'" %
|
||||
(key, self.default_locale))
|
||||
return key
|
||||
return value.encode('utf-8').format(*args, **kwargs)
|
||||
if self.default_locale != self.locale:
|
||||
logger.info("untranslated key '%s' for locale '%s'",
|
||||
key, self.locale)
|
||||
try:
|
||||
return _load_key(self.default_locale)
|
||||
except:
|
||||
pass
|
||||
logger.warning("unable to retrieve key '%s' for default locale '%s'",
|
||||
key, self.default_locale)
|
||||
return key
|
||||
|
||||
def _load_translations(self, locale, overwrite=False):
|
||||
"""Load translations for a locale
|
||||
|
@ -288,8 +301,8 @@ class Moulinette18n(object):
|
|||
|
||||
"""
|
||||
if not self._namespace:
|
||||
logging.error("attempt to retrieve translation for key '%s' " \
|
||||
"but no namespace is loaded" % key)
|
||||
logger.error("unable to retrieve translation for key '%s' without " \
|
||||
"loaded namespace", key)
|
||||
return key
|
||||
return self._namespace[1].translate(key, *args, **kwargs)
|
||||
|
||||
|
@ -319,13 +332,15 @@ class MoulinetteSignals(object):
|
|||
def set_handler(self, signal, handler):
|
||||
"""Set the handler for a signal"""
|
||||
if signal not in self.signals:
|
||||
raise ValueError("unknown signal '%s'" % signal)
|
||||
logger.error("unknown signal '%s'", signal)
|
||||
return
|
||||
setattr(self, '_%s' % signal, handler)
|
||||
|
||||
def clear_handler(self, signal):
|
||||
"""Clear the handler of a signal"""
|
||||
if signal not in self.signals:
|
||||
raise ValueError("unknown signal '%s'" % signal)
|
||||
logger.error("unknown signal '%s'", signal)
|
||||
return
|
||||
setattr(self, '_%s' % signal, self._notimplemented)
|
||||
|
||||
|
||||
|
@ -424,16 +439,17 @@ def init_interface(name, kwargs={}, actionsmap={}):
|
|||
|
||||
try:
|
||||
mod = import_module('moulinette.interfaces.%s' % name)
|
||||
except ImportError as e:
|
||||
# TODO: List available interfaces
|
||||
raise ImportError("Unable to load interface '%s': %s" % (name, str(e)))
|
||||
except ImportError:
|
||||
logger.exception("unable to load interface '%s'", name)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
else:
|
||||
try:
|
||||
# Retrieve interface classes
|
||||
parser = mod.ActionsMapParser
|
||||
interface = mod.Interface
|
||||
except AttributeError as e:
|
||||
raise ImportError("Invalid interface '%s': %s" % (name, e))
|
||||
except AttributeError:
|
||||
logger.exception("unable to retrieve classes of interface '%s'", name)
|
||||
raise MoulinetteError(errno.EIO, m18n.g('error_see_log'))
|
||||
|
||||
# Instantiate or retrieve ActionsMap
|
||||
if isinstance(actionsmap, dict):
|
||||
|
@ -441,7 +457,8 @@ def init_interface(name, kwargs={}, actionsmap={}):
|
|||
elif isinstance(actionsmap, ActionsMap):
|
||||
amap = actionsmap
|
||||
else:
|
||||
raise ValueError("Invalid actions map '%r'" % actionsmap)
|
||||
logger.error("invalid actionsmap value %r", actionsmap)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
|
||||
return interface(amap, **kwargs)
|
||||
|
||||
|
@ -459,10 +476,9 @@ def init_authenticator((vendor, name), kwargs={}):
|
|||
"""
|
||||
try:
|
||||
mod = import_module('moulinette.authenticators.%s' % vendor)
|
||||
except ImportError as e:
|
||||
# TODO: List available authenticators vendors
|
||||
raise ImportError("Unable to load authenticator vendor '%s': %s"
|
||||
% (vendor, str(e)))
|
||||
except ImportError:
|
||||
logger.exception("unable to load authenticator vendor '%s'", vendor)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
else:
|
||||
return mod.Authenticator(name, **kwargs)
|
||||
|
||||
|
@ -547,6 +563,8 @@ class MoulinetteLock(object):
|
|||
m18n.g('instance_already_running'))
|
||||
# Wait before checking again
|
||||
time.sleep(self.interval)
|
||||
|
||||
logger.debug('lock has been acquired')
|
||||
self._locked = True
|
||||
|
||||
def release(self):
|
||||
|
@ -558,6 +576,8 @@ class MoulinetteLock(object):
|
|||
if self._locked:
|
||||
if not self._bypass:
|
||||
os.unlink(self._lockfile)
|
||||
|
||||
logger.debug('lock has been released')
|
||||
self._locked = False
|
||||
|
||||
def __enter__(self):
|
||||
|
|
|
@ -5,6 +5,9 @@ import logging
|
|||
|
||||
from moulinette.core import (init_authenticator, MoulinetteError)
|
||||
|
||||
logger = logging.getLogger('moulinette.interface')
|
||||
|
||||
|
||||
# Base Class -----------------------------------------------------------
|
||||
|
||||
class BaseActionsMapParser(object):
|
||||
|
@ -24,6 +27,8 @@ class BaseActionsMapParser(object):
|
|||
if parent:
|
||||
self._o = parent
|
||||
else:
|
||||
logger.debug('initializing base actions map parser for %s',
|
||||
self.interface)
|
||||
msettings['interface'] = self.interface
|
||||
|
||||
self._o = self
|
||||
|
@ -216,8 +221,9 @@ class BaseActionsMapParser(object):
|
|||
# Store only if authentication is needed
|
||||
conf['authenticate'] = True if self.interface in ifaces else False
|
||||
else:
|
||||
# TODO: Log error instead and tell valid values
|
||||
raise MoulinetteError(errno.EINVAL, "Invalid value '%r' for configuration 'authenticate'" % ifaces)
|
||||
logger.error("expecting 'all', 'False' or a list for " \
|
||||
"configuration 'authenticate', got %r", ifaces)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
|
||||
# -- 'authenticator'
|
||||
try:
|
||||
|
@ -230,10 +236,13 @@ class BaseActionsMapParser(object):
|
|||
# Store needed authenticator profile
|
||||
conf['authenticator'] = self.global_conf['authenticator'][auth]
|
||||
except KeyError:
|
||||
raise MoulinetteError(errno.EINVAL, "Undefined authenticator '%s' in global configuration" % auth)
|
||||
logger.error("requesting profile '%s' which is undefined in " \
|
||||
"global configuration of 'authenticator'", auth)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
elif is_global and isinstance(auth, dict):
|
||||
if len(auth) == 0:
|
||||
logging.warning('no authenticator defined in global configuration')
|
||||
logger.warning('no profile defined in global configuration ' \
|
||||
"for 'authenticator'")
|
||||
else:
|
||||
auths = {}
|
||||
for auth_name, auth_conf in auth.items():
|
||||
|
@ -250,8 +259,9 @@ class BaseActionsMapParser(object):
|
|||
auth_conf.get('parameters', {}))
|
||||
conf['authenticator'] = auths
|
||||
else:
|
||||
# TODO: Log error instead and tell valid values
|
||||
raise MoulinetteError(errno.EINVAL, "Invalid value '%r' for configuration 'authenticator'" % auth)
|
||||
logger.error("expecting a dict of profile(s) or a profile name " \
|
||||
"for configuration 'authenticator', got %r", auth)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
|
||||
# -- 'argument_auth'
|
||||
try:
|
||||
|
@ -262,8 +272,9 @@ class BaseActionsMapParser(object):
|
|||
if isinstance(arg_auth, bool):
|
||||
conf['argument_auth'] = arg_auth
|
||||
else:
|
||||
# TODO: Log error instead and tell valid values
|
||||
raise MoulinetteError(errno.EINVAL, "Invalid value '%r' for configuration 'argument_auth'" % arg_auth)
|
||||
logger.error("expecting a boolean for configuration " \
|
||||
"'argument_auth', got %r", arg_auth)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
|
||||
# -- 'lock'
|
||||
try:
|
||||
|
@ -274,7 +285,9 @@ class BaseActionsMapParser(object):
|
|||
if isinstance(lock, bool):
|
||||
conf['lock'] = lock
|
||||
else:
|
||||
raise MoulinetteError(errno.EINVAL, "Invalid value '%r' for configuration 'lock'" % lock)
|
||||
logger.error("expecting a boolean for configuration 'lock', " \
|
||||
"got %r", lock)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
|
||||
return conf
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ from bottle import run, request, response, Bottle, HTTPResponse
|
|||
from moulinette.core import MoulinetteError, clean_session
|
||||
from moulinette.interfaces import (BaseActionsMapParser, BaseInterface)
|
||||
|
||||
logger = logging.getLogger('moulinette.interface.api')
|
||||
|
||||
|
||||
# API helpers ----------------------------------------------------------
|
||||
|
||||
def random_ascii(length=20):
|
||||
|
@ -291,7 +294,7 @@ class _ActionsMapPlugin(object):
|
|||
# Delete the current queue and break
|
||||
del self.queues[s_id]
|
||||
break
|
||||
logging.warning("invalid item in the messages queue: %r" % item)
|
||||
logger.exception("invalid item in the messages queue: %r", item)
|
||||
else:
|
||||
try:
|
||||
# Send the message
|
||||
|
@ -408,8 +411,8 @@ def error_to_response(error):
|
|||
errno.ENETUNREACH ]:
|
||||
return HTTPErrorResponse(error.strerror)
|
||||
else:
|
||||
logging.debug('unknown relevant response for error number %d - %s'
|
||||
% (error.errno, error.strerror))
|
||||
logger.debug('unknown relevant response for error [%s] %s',
|
||||
error.errno, error.strerror)
|
||||
return HTTPErrorResponse(error.strerror)
|
||||
|
||||
def format_for_response(content):
|
||||
|
@ -495,8 +498,8 @@ class ActionsMapParser(BaseActionsMapParser):
|
|||
try:
|
||||
keys.append(self._extract_route(r))
|
||||
except ValueError as e:
|
||||
logging.warning("cannot add api route '%s' for " \
|
||||
"action '%s': %s" % (r, tid, str(e)))
|
||||
logger.warning("cannot add api route '%s' for " \
|
||||
"action %s: %s", r, tid, e)
|
||||
continue
|
||||
if len(keys) == 0:
|
||||
raise ValueError("no valid api route found")
|
||||
|
@ -522,7 +525,8 @@ class ActionsMapParser(BaseActionsMapParser):
|
|||
# Retrieve the tid and the parser for the route
|
||||
tid, parser = self._parsers[route]
|
||||
except KeyError:
|
||||
raise MoulinetteError(errno.EINVAL, "No parser found for route '%s'" % route)
|
||||
logger.error("no argument parser found for route '%s'", route)
|
||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
||||
ret = argparse.Namespace()
|
||||
|
||||
if not self.get_conf(tid, 'lock'):
|
||||
|
@ -538,7 +542,6 @@ class ActionsMapParser(BaseActionsMapParser):
|
|||
# TODO: Catch errors
|
||||
auth = msignals.authenticate(klass(), **auth_conf)
|
||||
if not auth.is_authenticated:
|
||||
# TODO: Set proper error code
|
||||
raise MoulinetteError(errno.EACCES, m18n.g('authentication_required_long'))
|
||||
if self.get_conf(tid, 'argument_auth') and \
|
||||
self.get_conf(tid, 'authenticate') == 'all':
|
||||
|
@ -632,6 +635,9 @@ class Interface(BaseInterface):
|
|||
- port -- Server port to bind to
|
||||
|
||||
"""
|
||||
logger.debug("starting the server instance in %s:%d with websocket=%s",
|
||||
host, port, self.use_websocket)
|
||||
|
||||
try:
|
||||
if self.use_websocket:
|
||||
from gevent.pywsgi import WSGIServer
|
||||
|
@ -643,10 +649,12 @@ class Interface(BaseInterface):
|
|||
else:
|
||||
run(self._app, host=host, port=port)
|
||||
except IOError as e:
|
||||
logger.exception("unable to start the server instance on %s:%d",
|
||||
host, port)
|
||||
if e.args[0] == errno.EADDRINUSE:
|
||||
raise MoulinetteError(errno.EADDRINUSE,
|
||||
m18n.g('server_already_running'))
|
||||
raise
|
||||
raise MoulinetteError(errno.EIO, m18n.g('error_see_log'))
|
||||
|
||||
|
||||
## Routes handlers
|
||||
|
|
Loading…
Add table
Reference in a new issue