Univention Bugzilla – Bug 41354
ucsschool-import: support hooks using python code
Last modified: 2016-09-30 12:24:09 CEST
Support hooks using python code Additionally to the hooks supported by the ucs-school-lib (using expensive subprocess calls, but allowing to run any executable), the import-API should support calling pre- and post-hooks for add/modify/delete actions using Python code.
Implemented in r69557. Subclasses of ucsschool.importer.mass_import.user_import.UserImport can overwrite create_and_modify_hook(ImportUser, hook_time) and delete_hook(ImportUser, hook_time). (hook_time == pre|post) Modifications of user in create_and_modify_hook(user, "pre") will directly change the user before saving it in LDAP. I had thought about dynamically loading classes from predefined Python module paths. But the subclass approach is more in line with the rest of the API concept. The UserImport object can be retrieved from the factory with make_user_importer().
What is passed to create_and_modify_hook in "pre" and "post" condition? I think, an LDAP connection object should also be passed to the hook because there are hooks that alter other objects than the new/modified user. E.g. if a customer wants to create a samba share object for each created user.
The UserImport object has a "connection" attribute. It is documented in the docstring: def create_and_modify_hook(self, user, hook_time): """ Run code before or after creating or modifying a user. IMPLEMENT ME if you want to use a hook. You'll have full access to the data being saved to LDAP. It is much faster than running executables from /usr/share/ucs-school-import/hooks/*. * See user.action to know which action it is ("A" or "M"). * With action=A, if hook_time=pre the ImportUser does not exist in LDAP, yet. user.dn will be None. If hook_time=post user will be a opened ImportUser, loaded from LDAP. * With action=M, user is always a opened ImportUser, loaded from LDAP. * Use self.connection if you need a LDAP connection. :param user: ImportUser :param hook_time: str: either "pre" or "post" :return: None """ pass def delete_hook(self, user, hook_time): """ Run code before or after deleting a user. IMPLEMENT ME if you want to use a hook. You'll have full access to the data being saved to LDAP. It is much faster than running executables from /usr/share/ucs-school-import/hooks/*. * user is a opened ImportUser, loaded from LDAP. * Use self.connection if you need a LDAP connection. :param user: ImportUser :param hook_time: str: either "pre" or "post" :return: None """ pass
Why don't you split create_and_modify_hook(..., hook_time) into: pre_create_hook(), post_create_hook(), pre_modify_hook(), post_modify_hook()?
(In reply to Florian Best from comment #4) > Why don't you split create_and_modify_hook(..., hook_time) into: > pre_create_hook(), post_create_hook(), pre_modify_hook(), post_modify_hook()? I can't explain why I didn't do that before, but they are separated as proposed now: r69606. (Also removes a bug what action=="D".)
r70160: Added pyhooks for user.move operation.
PS: and an example: /usr/share/doc/ucs-school-import/hook_example.py
r70174: PyHook objects can now access the LDAP connection through the uldap object at self.lo.
Tested PyHooks via 34_import-users_via_cli_v2: - all (pre|post)(create|modify|remove) hooks are called as expected - input data can be modified in "pre" phase - working lo object is passed to hook Create a python hook file with filename suffix ".py" in /usr/share/ucs-school-import/pyhooks/user_(create|modify|remove)(pre|post).d/ and place there a subclass of PyHook. See /usr/share/doc/ucs-school-import/hook_example.py for an example.
UCS@school 4.1 R2 has been released: http://docs.software-univention.de/release-notes-ucsschool-4.1R2v1-de.pdf If this error occurs again, please use "Clone This Bug".