50 # passlib 1.5 wants calc_checksum, 1.6 wants _calc_checksum |
50 # passlib 1.5 wants calc_checksum, 1.6 wants _calc_checksum |
51 def calc_checksum(self, secret): |
51 def calc_checksum(self, secret): |
52 return md5crypt(secret, self.salt.encode('ascii')).decode('utf-8') |
52 return md5crypt(secret, self.salt.encode('ascii')).decode('utf-8') |
53 _calc_checksum = calc_checksum |
53 _calc_checksum = calc_checksum |
54 |
54 |
55 _CRYPTO_CTX = CryptContext(['sha512_crypt', CustomMD5Crypt, 'des_crypt']) |
55 _CRYPTO_CTX = CryptContext(['sha512_crypt', CustomMD5Crypt, 'des_crypt', 'ldap_salted_sha1']) |
56 |
56 |
57 def crypt_password(passwd, salt=None): |
57 def crypt_password(passwd, salt=None): |
58 """return the encrypted password using the given salt or a generated one |
58 """return the encrypted password using the given salt or a generated one |
59 """ |
59 """ |
60 if salt is None: |
60 if salt is None: |
137 name = repr(func) |
137 name = repr(func) |
138 return name |
138 return name |
139 |
139 |
140 class LoopTask(object): |
140 class LoopTask(object): |
141 """threaded task restarting itself once executed""" |
141 """threaded task restarting itself once executed""" |
142 def __init__(self, repo, interval, func, args): |
142 def __init__(self, tasks_manager, interval, func, args): |
143 if interval <= 0: |
143 if interval <= 0: |
144 raise ValueError('Loop task interval must be > 0 ' |
144 raise ValueError('Loop task interval must be > 0 ' |
145 '(current value: %f for %s)' % \ |
145 '(current value: %f for %s)' % \ |
146 (interval, func_name(func))) |
146 (interval, func_name(func))) |
147 self.repo = repo |
147 self._tasks_manager = tasks_manager |
148 self.interval = interval |
148 self.interval = interval |
149 def auto_restart_func(self=self, func=func, args=args): |
149 def auto_restart_func(self=self, func=func, args=args): |
150 restart = True |
150 restart = True |
151 try: |
151 try: |
152 func(*args) |
152 func(*args) |
155 logger.exception('Unhandled exception in LoopTask %s', self.name) |
155 logger.exception('Unhandled exception in LoopTask %s', self.name) |
156 raise |
156 raise |
157 except BaseException: |
157 except BaseException: |
158 restart = False |
158 restart = False |
159 finally: |
159 finally: |
160 if restart and not self.repo.shutting_down: |
160 if restart and tasks_manager.running: |
161 self.start() |
161 self.start() |
162 self.func = auto_restart_func |
162 self.func = auto_restart_func |
163 self.name = func_name(func) |
163 self.name = func_name(func) |
164 |
164 |
165 def __str__(self): |
165 def __str__(self): |
201 self.daemon = True |
201 self.daemon = True |
202 Thread.start(self) |
202 Thread.start(self) |
203 |
203 |
204 def getName(self): |
204 def getName(self): |
205 return '%s(%s)' % (self._name, Thread.getName(self)) |
205 return '%s(%s)' % (self._name, Thread.getName(self)) |
|
206 |
|
207 class TasksManager(object): |
|
208 """Object dedicated manage background task""" |
|
209 |
|
210 def __init__(self): |
|
211 self.running = False |
|
212 self._tasks = [] |
|
213 self._looping_tasks = [] |
|
214 |
|
215 def add_looping_task(self, interval, func, *args): |
|
216 """register a function to be called every `interval` seconds. |
|
217 |
|
218 looping tasks can only be registered during repository initialization, |
|
219 once done this method will fail. |
|
220 """ |
|
221 task = LoopTask(self, interval, func, args) |
|
222 if self.running: |
|
223 self._start_task(task) |
|
224 else: |
|
225 self._tasks.append(task) |
|
226 |
|
227 def _start_task(self, task): |
|
228 self._looping_tasks.append(task) |
|
229 self.info('starting task %s with interval %.2fs', task.name, |
|
230 task.interval) |
|
231 task.start() |
|
232 |
|
233 def start(self): |
|
234 """Start running looping task""" |
|
235 assert self.running == False # bw compat purpose maintly |
|
236 while self._tasks: |
|
237 task = self._tasks.pop() |
|
238 self._start_task(task) |
|
239 self.running = True |
|
240 |
|
241 def stop(self): |
|
242 """Stop all running task. |
|
243 |
|
244 returns when all task have been cancel and none are running anymore""" |
|
245 if self.running: |
|
246 while self._looping_tasks: |
|
247 looptask = self._looping_tasks.pop() |
|
248 self.info('canceling task %s...', looptask.name) |
|
249 looptask.cancel() |
|
250 looptask.join() |
|
251 self.info('task %s finished', looptask.name) |
|
252 |
|
253 from logging import getLogger |
|
254 from cubicweb import set_log_methods |
|
255 set_log_methods(TasksManager, getLogger('cubicweb.repository')) |
|
256 |