[enh] Adapt yunohost_hook.py and allow bypass of the locking process

This commit is contained in:
kload 2014-04-24 11:35:18 +00:00
parent 18eb0f9406
commit 962b78329f
6 changed files with 98 additions and 56 deletions

View file

@ -50,6 +50,7 @@ _global:
uri: ldap://localhost:389 uri: ldap://localhost:389
base_dn: dc=yunohost,dc=org base_dn: dc=yunohost,dc=org
argument_auth: true argument_auth: true
lock: true
arguments: arguments:
-v: -v:
full: --version full: --version
@ -70,6 +71,7 @@ user:
api: GET /users api: GET /users
configuration: configuration:
authenticate: all authenticate: all
authenticator: ldap-anonymous
arguments: arguments:
--fields: --fields:
help: fields to fetch help: fields to fetch
@ -183,6 +185,7 @@ user:
api: 'GET /users/<username>' api: 'GET /users/<username>'
configuration: configuration:
authenticate: all authenticate: all
authenticator: ldap-anonymous
arguments: arguments:
username: username:
help: Username or mail to get informations help: Username or mail to get informations
@ -201,6 +204,7 @@ domain:
api: GET /domains api: GET /domains
configuration: configuration:
authenticate: all authenticate: all
authenticator: ldap-anonymous
arguments: arguments:
-f: -f:
full: --filter full: --filter
@ -361,6 +365,8 @@ app:
api: POST /app api: POST /app
configuration: configuration:
authenticate: all authenticate: all
authenticator: ldap-anonymous
lock: false
arguments: arguments:
app: app:
help: App to install help: App to install
@ -375,6 +381,9 @@ app:
remove: remove:
action_help: Remove app action_help: Remove app
api: DELETE /app api: DELETE /app
configuration:
authenticate: all
authenticator: ldap-anonymous
arguments: arguments:
app: app:
help: App(s) to delete help: App(s) to delete
@ -383,6 +392,9 @@ app:
upgrade: upgrade:
action_help: Upgrade app action_help: Upgrade app
api: PUT /app api: PUT /app
configuration:
authenticate: all
authenticator: ldap-anonymous
arguments: arguments:
app: app:
help: App(s) to upgrade (default all) help: App(s) to upgrade (default all)
@ -450,6 +462,7 @@ app:
api: GET /app/checkurl api: GET /app/checkurl
configuration: configuration:
authenticate: all authenticate: all
authenticator: ldap-anonymous
arguments: arguments:
url: url:
help: Url to check help: Url to check
@ -480,6 +493,7 @@ app:
api: PUT /ssowatconf api: PUT /ssowatconf
configuration: configuration:
authenticate: all authenticate: all
authenticator: ldap-anonymous
### app_addaccess() TODO: Write help ### app_addaccess() TODO: Write help
addaccess: addaccess:
@ -487,6 +501,7 @@ app:
api: PUT /app/access api: PUT /app/access
configuration: configuration:
authenticate: all authenticate: all
authenticator: ldap-anonymous
arguments: arguments:
apps: apps:
nargs: "+" nargs: "+"
@ -500,6 +515,7 @@ app:
api: DELETE /app/access api: DELETE /app/access
configuration: configuration:
authenticate: all authenticate: all
authenticator: ldap-anonymous
arguments: arguments:
apps: apps:
nargs: "+" nargs: "+"
@ -513,6 +529,7 @@ app:
api: POST /app/access api: POST /app/access
configuration: configuration:
authenticate: all authenticate: all
authenticator: ldap-anonymous
arguments: arguments:
apps: apps:
nargs: "+" nargs: "+"

View file

@ -23,15 +23,13 @@
Manage hooks Manage hooks
""" """
import logging
logging.warning('the module yunohost.hook has not been revisited and updated yet')
import os import os
import sys import sys
import re import re
import json import json
from moulinette.helpers import YunoHostError, YunoHostLDAP, win_msg, colorize from moulinette.helpers import colorize
from moulinette.core import MoulinetteError
hook_folder = '/usr/share/yunohost/hooks/' hook_folder = '/usr/share/yunohost/hooks/'
@ -56,8 +54,8 @@ def hook_add(app, file):
finalpath = hook_folder + action +'/'+ priority +'-'+ app finalpath = hook_folder + action +'/'+ priority +'-'+ app
print app print app
os.system('cp '+ file +' '+ finalpath) os.system('cp %s %s' % (file, finalpath))
os.system('chown -hR admin: '+ hook_folder) os.system('chown -hR admin: %s' % hook_folder)
return { 'hook': finalpath } return { 'hook': finalpath }
@ -87,7 +85,6 @@ def hook_callback(action, args=None):
args -- Ordered list of arguments to pass to the script args -- Ordered list of arguments to pass to the script
""" """
with YunoHostLDAP() as yldap:
try: os.listdir(hook_folder + action) try: os.listdir(hook_folder + action)
except OSError: pass except OSError: pass
else: else:
@ -114,7 +111,7 @@ def hook_check(file):
with open(file[:file.index('scripts/')] + 'manifest.json') as f: with open(file[:file.index('scripts/')] + 'manifest.json') as f:
manifest = json.loads(str(f.read())) manifest = json.loads(str(f.read()))
except: except:
raise YunoHostError(22, _("Invalid app package")) raise MoulinetteError(22, _("Invalid app package"))
action = file[file.index('scripts/') + 8:] action = file[file.index('scripts/') + 8:]
if 'arguments' in manifest and action in manifest['arguments']: if 'arguments' in manifest and action in manifest['arguments']:
@ -132,7 +129,6 @@ def hook_exec(file, args=None):
args -- Arguments to pass to the script args -- Arguments to pass to the script
""" """
with YunoHostLDAP() as yldap:
if isinstance(args, list): if isinstance(args, list):
arg_list = args arg_list = args
else: else:
@ -144,7 +140,7 @@ def hook_exec(file, args=None):
for arg in required_args: for arg in required_args:
if arg['name'] in args: if arg['name'] in args:
if 'choices' in arg and args[arg['name']] not in arg['choices']: if 'choices' in arg and args[arg['name']] not in arg['choices']:
raise YunoHostError(22, _("Invalid choice") + ': ' + args[arg['name']]) raise MoulinetteError(22, _("Invalid choice") + ': ' + args[arg['name']])
arg_list.append(args[arg['name']]) arg_list.append(args[arg['name']])
else: else:
if os.isatty(1) and 'ask' in arg: if os.isatty(1) and 'ask' in arg:
@ -163,10 +159,11 @@ def hook_exec(file, args=None):
elif 'default' in arg: elif 'default' in arg:
arg_list.append(arg['default']) arg_list.append(arg['default'])
else: else:
raise YunoHostError(22, _("Missing arguments") + ': ' + arg['name']) raise MoulinetteError(22, _("Missing argument : %s") % arg['name'])
file_path = "./" file_path = "./"
if "/" in file and file[0:2] != file_path: if "/" in file and file[0:2] != file_path:
file_path = os.path.dirname(file) file_path = os.path.dirname(file)
file = file.replace(file_path +"/", "") file = file.replace(file_path +"/", "")
return os.system('su - admin -c "cd \\"'+ file_path +'\\" && bash \\"'+ file +'\\" '+ ' '.join(arg_list) +'"') #TODO: Allow python script return os.system('su - admin -c "cd \\"%s\\" && bash \\"%s\\" %s"' % (file_path, file, ' '.join(arg_list)))
#TODO: Allow python script

View file

@ -347,6 +347,7 @@ class MoulinetteLock(object):
self._lockfile = '/var/run/moulinette_%s.lock' % namespace self._lockfile = '/var/run/moulinette_%s.lock' % namespace
self._locked = False self._locked = False
self._bypass = False
def acquire(self): def acquire(self):
"""Attempt to acquire the lock for the moulinette instance """Attempt to acquire the lock for the moulinette instance
@ -359,9 +360,16 @@ class MoulinetteLock(object):
start_time = time.time() start_time = time.time()
while True: while True:
if 'BYPASS_LOCK' in os.environ and os.environ['BYPASS_LOCK'] == 'yes':
self._bypass = True
break
if not os.path.isfile(self._lockfile): if not os.path.isfile(self._lockfile):
# Create the lock file # Create the lock file
try:
(open(self._lockfile, 'w')).close() (open(self._lockfile, 'w')).close()
except IOError:
raise MoulinetteError(errno.EPERM, _("Permission denied, did you forget 'sudo' ?"))
break break
if (time.time() - start_time) > self.timeout: if (time.time() - start_time) > self.timeout:
@ -378,6 +386,7 @@ class MoulinetteLock(object):
""" """
if self._locked: if self._locked:
if not self._bypass:
os.unlink(self._lockfile) os.unlink(self._lockfile)
self._locked = False self._locked = False

View file

@ -263,6 +263,17 @@ class BaseActionsMapParser(object):
# TODO: Log error instead and tell valid values # TODO: Log error instead and tell valid values
raise MoulinetteError(errno.EINVAL, "Invalid value '%r' for configuration 'argument_auth'" % arg_auth) raise MoulinetteError(errno.EINVAL, "Invalid value '%r' for configuration 'argument_auth'" % arg_auth)
# -- 'lock'
try:
lock = configuration['lock']
except KeyError:
pass
else:
if isinstance(lock, bool):
conf['lock'] = lock
else:
raise MoulinetteError(errno.EINVAL, "Invalid value '%r' for configuration 'lock'" % lock)
return conf return conf
def _format_conf(self, name, value): def _format_conf(self, name, value):

View file

@ -393,6 +393,10 @@ class ActionsMapParser(BaseActionsMapParser):
raise MoulinetteError(errno.EINVAL, "No parser found for route '%s'" % route) raise MoulinetteError(errno.EINVAL, "No parser found for route '%s'" % route)
ret = argparse.Namespace() ret = argparse.Namespace()
if not self.get_conf(tid, 'lock'):
os.environ['BYPASS_LOCK'] = 'yes'
# Perform authentication if needed # Perform authentication if needed
if self.get_conf(tid, 'authenticate'): if self.get_conf(tid, 'authenticate'):
auth_conf, klass = self.get_conf(tid, 'authenticator') auth_conf, klass = self.get_conf(tid, 'authenticator')

View file

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os
import errno import errno
import getpass import getpass
import argparse import argparse
@ -126,6 +127,9 @@ class ActionsMapParser(BaseActionsMapParser):
def parse_args(self, args, **kwargs): def parse_args(self, args, **kwargs):
ret = self._parser.parse_args(args) ret = self._parser.parse_args(args)
if not self.get_conf(ret._tid, 'lock'):
os.environ['BYPASS_LOCK'] = 'yes'
# Perform authentication if needed # Perform authentication if needed
if self.get_conf(ret._tid, 'authenticate'): if self.get_conf(ret._tid, 'authenticate'):
auth_conf, klass = self.get_conf(ret._tid, 'authenticator') auth_conf, klass = self.get_conf(ret._tid, 'authenticator')