How to deal with hook common code?


#1

This is a question for people experienced with hook development.

I have severak hooks set up to “do stuff in common”: queuejob, runjob and modifyjob. As the hooks do “similar” stuff (adding or removing holds, adding to select - or removing what was added), there is quite a bit of code, which is common for all the hooks. Normally, I might put this in a separate module - to be included in each python script. Or I could put the common lines in a separate file, to be read and executed, as per

with open(libfil) as reserve_pylib:
  exec(reserve_pylib.read())

However, I should very much like if other/experienced developers could give examples, on how this (smallish) issue may/should be addressed. All input is more than welcome. As there are for sure several (bordering on many) ways to do this, I hope other people will be interested in the responses as well.

For now, I use the “direct inclusion” shown above - and I put the actual “hook library file” in a directory created for the purpose (${PBS_EXEC}/hooklibs/). Obviously, I do include a few more checks, and error-logging in case stuff fails.

Best,

Bjarne


#2

Simple experimentation shows that “direct inclusion” as per

with open(libfil) as reserve_pylib:
  exec(reserve_pylib.read())

has at least one significant draw-back: The common code is compiled not just once - but every time the hook is executed. So, it is not efficient.

Presently, I’ll take an approach, where I actually merge the source files with a common-block file, prior to inclusion (import hook) in PBS. Thus, the file, which is actually imported in created “on the fly” - by inserting the common-core code file at a particular key word in the hook file.

This may not be very “elegant”, but it could work like a make-based system and has the advantages:

  • Common lines are maintained only in a single place
  • The PBS pro interface is completely straight forward, with no special steps
  • It may work as a make-based system

/Bjarne


#3

Hello Bjarne,

I used “hook handlers” in the cgroups hook to accomplish this. The same hook gets called for multiple events, and a different handler is defined for each event type. The hook contains several common classes and methods that are utilized to handle the various events. Have a look at the HookUtils class here: https://github.com/PBSPro/pbspro/blob/master/src/hooks/cgroups/pbs_cgroups.py

That way everything gets packaged together and each hook event type has access to all of the defined classes. The cgroups hook is undergoing some refactoring at the moment, but the overall technique of “hook handlers” will be retained.

Thanks,

Mike


#4

Hi Mike,

That’s a very elaborate piece of code.

If I understand you correctly, then the main suggestion is to use put all the code in a single hook (file), and let the behaviour of that file depend on pbs.event().type - plus data from an input/config file (in this case JSON). Then the hook trigger events (defined in by qmgr) can be a list of all the events, which should evoke the hook.

That is a much better method than what I was using.

EDIT: I presently see only one possible drawback of the method outlined by Mike: namely that the hook must then use the same ordering qmgr -c "set hook <HOOKNAME> order = <N> for all select events. This is not a show-stopper for me, but it may require some consideration on sites with several of these “multi-event” hooks.
In a scenario, where there are two different “multi-event” of hooks (different code bases: hook1 and hook2), and - say - hook1 must run before hook2 on queuejob events, but hook2 before hook1 on runjob events, then the solution is not straight-forward.

Thanks,

/Bjarne

PS: I guess cgroups is just a name for this hook system (I find no reference to “cgroup” in the Admin Guide. In the Ref Guide, the phrase is used as part of the fairshare usage, but I presume that is a quite different usage.)


#5

Hello Bjarne,

Cgroup support is still in beta, and not yet documented. The existing hooks were added to the PBS Pro repository so that future changes could be tracked in GitHub. I’m in the process of refactoring all of the changes that have gone in for the past several months.

I believe you understand the point I was trying to make about lumping everything into a single hook that reacts appropriately to different events. You are correct about the hook ordering… the admin loses some flexibility there. That is something we might consider addressing in the future if there is sufficient demand. Glad you found the reference helpful.

Thanks,

Mike