1 |
commit: df58d07cbadab7bdd5f6a494355c8dac9f840d09 |
2 |
Author: André Erdmann <dywi <AT> mailerd <DOT> de> |
3 |
AuthorDate: Tue Jun 25 21:08:01 2013 +0000 |
4 |
Commit: André Erdmann <dywi <AT> mailerd <DOT> de> |
5 |
CommitDate: Tue Jun 25 21:08:01 2013 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=df58d07c |
7 |
|
8 |
EVENT_HOOK_RESTRICT, roverlay.hook |
9 |
|
10 |
--- |
11 |
roverlay/config/const.py | 4 ++ |
12 |
roverlay/config/entrymap.py | 29 +++++--- |
13 |
roverlay/hook.py | 169 ++++++++++++++++++++++++++++++++++++++++++++ |
14 |
roverlay/main.py | 7 +- |
15 |
roverlay/tools/shenv.py | 22 ++---- |
16 |
5 files changed, 204 insertions(+), 27 deletions(-) |
17 |
|
18 |
diff --git a/roverlay/config/const.py b/roverlay/config/const.py |
19 |
index 4ee9d45..f9a2e14 100644 |
20 |
--- a/roverlay/config/const.py |
21 |
+++ b/roverlay/config/const.py |
22 |
@@ -78,6 +78,10 @@ _CONSTANTS = dict ( |
23 |
manifest_implementation = 'default', |
24 |
), |
25 |
|
26 |
+ EVENT_HOOK = dict ( |
27 |
+ default_exe_relpath = [ 'hooks', 'mux.sh' ], |
28 |
+ ), |
29 |
+ |
30 |
TOOLS = dict ( |
31 |
EBUILD = dict ( |
32 |
exe = "/usr/bin/ebuild", |
33 |
|
34 |
diff --git a/roverlay/config/entrymap.py b/roverlay/config/entrymap.py |
35 |
index 136b4b5..6a282d9 100644 |
36 |
--- a/roverlay/config/entrymap.py |
37 |
+++ b/roverlay/config/entrymap.py |
38 |
@@ -306,6 +306,12 @@ CONFIG_ENTRY_MAP = dict ( |
39 |
value_type = yesno, |
40 |
), |
41 |
|
42 |
+ overlay_distmap_file = dict ( |
43 |
+ path = [ 'OVERLAY', 'DISTMAP', 'dbfile', ] |
44 |
+ value_type = 'fs_file', |
45 |
+ description = 'distmap file', |
46 |
+ ), |
47 |
+ |
48 |
# * alias |
49 |
backup_desc = 'overlay_backup_desc', |
50 |
eclass = 'overlay_eclass', |
51 |
@@ -316,6 +322,7 @@ CONFIG_ENTRY_MAP = dict ( |
52 |
distdir_strategy = 'overlay_distdir_strategy', |
53 |
distdir_flat = 'overlay_distdir_flat', |
54 |
distdir_verify = 'overlay_distdir_verify', |
55 |
+ distmap_file = 'overlay_distmap_file', |
56 |
|
57 |
# --- overlay |
58 |
|
59 |
@@ -449,14 +456,22 @@ CONFIG_ENTRY_MAP = dict ( |
60 |
description = 'filter shell env', |
61 |
), |
62 |
|
63 |
- hook_script = dict ( |
64 |
- path = [ 'SHELL_ENV', 'hook', ], |
65 |
- value_type = 'fs_file', |
66 |
+ event_hook = dict ( |
67 |
+ path = [ 'EVENT_HOOK', 'exe', ], |
68 |
+ value_type = 'fs_file', |
69 |
description = 'script that is run on certain events, e.g. overlay_success', |
70 |
), |
71 |
|
72 |
+ event_hook_restrict = dict ( |
73 |
+ path = [ 'EVENT_HOOK', 'restrict', ], |
74 |
+ value_type = 'list:str', |
75 |
+ description = 'mask for running hooks', |
76 |
+ ), |
77 |
+ |
78 |
+ |
79 |
# * alias |
80 |
- hook = 'hook_script', |
81 |
+ hook = 'event_hook', |
82 |
+ hook_restrict = 'event_hook_restrict', |
83 |
|
84 |
|
85 |
# == other == |
86 |
@@ -467,12 +482,6 @@ CONFIG_ENTRY_MAP = dict ( |
87 |
description = 'directory for cache data', |
88 |
), |
89 |
|
90 |
- tmpdir = dict ( |
91 |
- path = [ 'TMPDIR', 'root', ], |
92 |
- value_type = 'fs_dir', |
93 |
- description = 'directory for temporary data', |
94 |
- ), |
95 |
- |
96 |
nosync = dict ( |
97 |
value_type = yesno, |
98 |
description = 'forbid/allow syncing with remotes', |
99 |
|
100 |
diff --git a/roverlay/hook.py b/roverlay/hook.py |
101 |
new file mode 100644 |
102 |
index 0000000..3b13315 |
103 |
--- /dev/null |
104 |
+++ b/roverlay/hook.py |
105 |
@@ -0,0 +1,169 @@ |
106 |
+# R overlay -- run roverlay hooks (shell scripts) |
107 |
+# -*- coding: utf-8 -*- |
108 |
+# Copyright (C) 2013 André Erdmann <dywi@×××××××.de> |
109 |
+# Distributed under the terms of the GNU General Public License; |
110 |
+# either version 2 of the License, or (at your option) any later version. |
111 |
+ |
112 |
+import os.path |
113 |
+import logging |
114 |
+ |
115 |
+import roverlay.config |
116 |
+import roverlay.tools.shenv |
117 |
+ |
118 |
+__all__ = [ 'run_hook', 'phase_allowed', ] |
119 |
+ |
120 |
+LOGGER = logging.getLogger ( 'event_hook' ) |
121 |
+ |
122 |
+ |
123 |
+_EVENT_SCRIPT = None |
124 |
+ |
125 |
+# None|iterable _EVENT_RESTRICT |
126 |
+_EVENT_RESTRICT = None |
127 |
+ |
128 |
+# int _EVENT_POLICY |
129 |
+# -1: no policy (allow all) |
130 |
+# 0: not configured |
131 |
+# 1: allow unless in _EVENT_RESTRICT (blacklist) |
132 |
+# 2: deny unless in _EVENT_RESTRICT (whitelist) |
133 |
+# 4: deny all |
134 |
+_EVENT_POLICY = 0 |
135 |
+ |
136 |
+def setup(): |
137 |
+ global _EVENT_SCRIPT |
138 |
+ global _EVENT_POLICY |
139 |
+ global _EVENT_RESTRICT |
140 |
+ |
141 |
+ _EVENT_SCRIPT = roverlay.config.get ( 'EVENT_HOOK.exe', False ) |
142 |
+ if _EVENT_SCRIPT is False: |
143 |
+ a_dir = roverlay.config.get ( 'OVERLAY.additions_dir', None ) |
144 |
+ if a_dir: |
145 |
+ s = os.path.join ( |
146 |
+ a_dir, |
147 |
+ *roverlay.config.get_or_fail ( 'EVENT_HOOK.default_exe_relpath' ) |
148 |
+ ) |
149 |
+ if os.path.isfile ( s ): |
150 |
+ _EVENT_SCRIPT = s |
151 |
+ # -- end if _EVENT_SCRIPT |
152 |
+ |
153 |
+ conf_restrict = roverlay.config.get ( 'EVENT_HOOK.restrict', False ) |
154 |
+ |
155 |
+ if conf_restrict: |
156 |
+ # tristate None,False,True |
157 |
+ is_whitelist = None |
158 |
+ allow = set() |
159 |
+ deny = set() |
160 |
+ for p in conf_restrict: |
161 |
+ if p == '*': |
162 |
+ # "allow all" |
163 |
+ is_whitelist = False |
164 |
+ elif p == '-*': |
165 |
+ # "deny all" |
166 |
+ is_whitelist = True |
167 |
+ elif p == '-' or p == '+': |
168 |
+ # empty |
169 |
+ pass |
170 |
+ elif p[0] == '-': |
171 |
+ # deny <k> |
172 |
+ k = p[1:].lower() |
173 |
+ deny.add ( k ) |
174 |
+ try: |
175 |
+ allow.remove ( k ) |
176 |
+ except KeyError: |
177 |
+ pass |
178 |
+ else: |
179 |
+ # allow <k> |
180 |
+ k = ( p[1:] if p[0] == '+' else p ).lower() |
181 |
+ allow.add ( k ) |
182 |
+ try: |
183 |
+ deny.remove ( k ) |
184 |
+ except KeyError: |
185 |
+ pass |
186 |
+ # -- end for; |
187 |
+ |
188 |
+ if is_whitelist is None: |
189 |
+ # allow is set => is whitelist |
190 |
+ # neither allow nor deny are set => deny allow |
191 |
+ is_whitelist = bool ( allow or not deny ) |
192 |
+ # -- end if is_whitelist #1 |
193 |
+ |
194 |
+ if is_whitelist: |
195 |
+ if allow: |
196 |
+ _EVENT_RESTRICT = frozenset ( allow ) |
197 |
+ _EVENT_POLICY = 2 |
198 |
+ else: |
199 |
+ _EVENT_POLICY = 4 |
200 |
+ elif deny: |
201 |
+ _EVENT_RESTRICT = frozenset ( deny ) |
202 |
+ _EVENT_POLICY = 1 |
203 |
+ else: |
204 |
+ _EVENT_POLICY = -1 |
205 |
+ # -- end if is_whitelist #2 |
206 |
+ else: |
207 |
+ _EVENT_POLICY = -1 |
208 |
+ # -- end if conf_restrict |
209 |
+# --- end of setup (...) --- |
210 |
+ |
211 |
+def phase_allowed ( phase ): |
212 |
+ if _EVENT_POLICY == -1: |
213 |
+ return True |
214 |
+ elif _EVENT_POLICY == 1: |
215 |
+ # allow unless in restrict |
216 |
+ if phase not in _EVENT_RESTRICT: |
217 |
+ return True |
218 |
+ else: |
219 |
+ LOGGER.debug ( |
220 |
+ "phase {!r} denied by blacklist policy.".format ( phase ) |
221 |
+ ) |
222 |
+ elif _EVENT_POLICY == 2: |
223 |
+ # deny unless in restrict |
224 |
+ if phase in _EVENT_RESTRICT: |
225 |
+ return True |
226 |
+ else: |
227 |
+ LOGGER.debug ( |
228 |
+ "phase {!r} denied by whitelist policy.".format ( phase ) |
229 |
+ ) |
230 |
+ elif _EVENT_POLICY == 4: |
231 |
+ LOGGER.debug ( |
232 |
+ "phase {!r} denied by 'deny all' policy".format ( phase ) |
233 |
+ ) |
234 |
+ else: |
235 |
+ LOGGER.warning ( |
236 |
+ "phase {!r} denied by undefined policy {} (fix this)".format ( |
237 |
+ phase, _EVENT_POLICY |
238 |
+ ) |
239 |
+ ) |
240 |
+ # -- end if _EVENT_POLICY |
241 |
+ |
242 |
+ # default return |
243 |
+ return False |
244 |
+# --- end of phase_allowed (...) --- |
245 |
+ |
246 |
+def phase_allowed_nolog ( phase ): |
247 |
+ return ( |
248 |
+ _EVENT_POLICY == -1 |
249 |
+ ) or ( |
250 |
+ _EVENT_POLICY == 1 and phase not in _EVENT_RESTRICT |
251 |
+ ) or ( |
252 |
+ _EVENT_POLICY == 2 and phase in _EVENT_RESTRICT |
253 |
+ ) |
254 |
+# --- end of phase_allowed_nolog (...) --- |
255 |
+ |
256 |
+def run ( phase ): |
257 |
+ if _EVENT_SCRIPT is None: |
258 |
+ LOGGER.warning ( |
259 |
+ "hook module not initialized - doing that now (FIXME!)" |
260 |
+ ) |
261 |
+ setup() |
262 |
+ |
263 |
+ |
264 |
+ |
265 |
+ if _EVENT_SCRIPT and phase_allowed ( phase ): |
266 |
+ return roverlay.tools.shenv.run_script ( |
267 |
+ _EVENT_SCRIPT, phase, return_success=True |
268 |
+ ) |
269 |
+ else: |
270 |
+ # nop |
271 |
+ return True |
272 |
+# --- end of run (...) --- |
273 |
+ |
274 |
+run_hook = run |
275 |
|
276 |
diff --git a/roverlay/main.py b/roverlay/main.py |
277 |
index 901cbcf..4822e21 100644 |
278 |
--- a/roverlay/main.py |
279 |
+++ b/roverlay/main.py |
280 |
@@ -289,7 +289,7 @@ def main ( |
281 |
# this hook should be called _after_ verifying the overlay |
282 |
# (verification is not implemented yet) |
283 |
# |
284 |
- if not roverlay.tools.shenv.run_hook ( 'overlay_success' ): |
285 |
+ if not roverlay.hook.run ( 'overlay_success' ): |
286 |
die ( "overlay_success hook returned non-zero", DIE.OV_CREATE ) |
287 |
|
288 |
set_action_done ( "create" ) |
289 |
@@ -476,7 +476,7 @@ def main ( |
290 |
from roverlay.overlay.creator import OverlayCreator |
291 |
|
292 |
import roverlay.config |
293 |
- import roverlay.tools.shenv |
294 |
+ import roverlay.hook |
295 |
except ImportError: |
296 |
if HIDE_EXCEPTIONS: |
297 |
die ( "Cannot import roverlay modules!", DIE.IMPORT ) |
298 |
@@ -491,6 +491,9 @@ def main ( |
299 |
|
300 |
# -- run |
301 |
|
302 |
+ # initialize roverlay.hook |
303 |
+ roverlay.hook.setup() |
304 |
+ |
305 |
# always run sync 'cause commands = {create,sync,apply_rules} |
306 |
# and create,apply_rules implies (no)sync |
307 |
run_sync() |
308 |
|
309 |
diff --git a/roverlay/tools/shenv.py b/roverlay/tools/shenv.py |
310 |
index 85644d4..f0c054b 100644 |
311 |
--- a/roverlay/tools/shenv.py |
312 |
+++ b/roverlay/tools/shenv.py |
313 |
@@ -1,4 +1,4 @@ |
314 |
-# R overlay -- tools, run roverlay hooks (shell scripts) |
315 |
+# R overlay -- tools, shell script environment |
316 |
# -*- coding: utf-8 -*- |
317 |
# Copyright (C) 2013 André Erdmann <dywi@×××××××.de> |
318 |
# Distributed under the terms of the GNU General Public License; |
319 |
@@ -8,6 +8,7 @@ import logging |
320 |
import os |
321 |
import subprocess |
322 |
import tempfile |
323 |
+import time |
324 |
|
325 |
|
326 |
import roverlay.config |
327 |
@@ -18,7 +19,6 @@ import roverlay.util |
328 |
# _SHELL_ENV, _SHELL_INTPR are created when calling run_script() |
329 |
# |
330 |
_SHELL_ENV = None |
331 |
-_SHELL_ENV_SCRIPT = None |
332 |
#_SHELL_INTPR = None |
333 |
LOGGER = logging.getLogger ( 'shenv' ) |
334 |
|
335 |
@@ -287,7 +287,11 @@ def run_script ( script, phase, return_success=False, logger=None ): |
336 |
|
337 |
output = script_call.communicate() |
338 |
except: |
339 |
- script_call.kill() |
340 |
+ try: |
341 |
+ script_call.terminate() |
342 |
+ time.sleep ( 1 ) |
343 |
+ finally: |
344 |
+ script_call.kill() |
345 |
raise |
346 |
|
347 |
|
348 |
@@ -327,15 +331,3 @@ def run_script ( script, phase, return_success=False, logger=None ): |
349 |
else: |
350 |
return script_call |
351 |
# --- end of run_script (...) --- |
352 |
- |
353 |
-def run_hook ( phase ): |
354 |
- global _SHELL_ENV_SCRIPT |
355 |
- if _SHELL_ENV_SCRIPT is None: |
356 |
- _SHELL_ENV_SCRIPT = roverlay.config.get ( 'SHELL_ENV.hook', False ) |
357 |
- |
358 |
- if _SHELL_ENV_SCRIPT: |
359 |
- return run_script ( _SHELL_ENV_SCRIPT, phase, return_success=True ) |
360 |
- else: |
361 |
- # nop |
362 |
- return True |
363 |
-# --- end of run_hook (...) --- |