Ed Brown wrote: > On Thu, 2005-05-12 at 09:20, Brendan Strejcek wrote: > > cfagent could figure out all ordering using class dependencies. > > Could you illustrate this with an example? Is this tied in with the > hierarchy of imports, or am I not getting it? I'm really interested in > seeing how another approach can improve flexibility and simplicity of > ordering operations by cfengine, when that's necessary.
Here is an example. Say you have a daemon config file that you want to edit. After you edit this file you will need to restart the daemon. For the sake of the example, assume that restarting the daemon causes some logfile permissions to get messed up, so upon a successful restart of the daemon, you will also need to check and correct the permissions of the log file. Thus, a clear ordering of the three actions is necessary. Using the present cfengine, this might be accomplished by something like: control: actionsequence = ( editfiles shellcommands files ) editfiles: { /daemon/config/file # Edits DefineClasses "daemon_config_file_edited" } shellcommands: daemon_config_file_edited:: "/some/daemon/command restart" define=daemon_restarted files: daemon_restarted:: /some/daemon/log/file mode=some_mode owner=some_uid group=some_gid action=fixall This works, but is problematic because you may have another set of operations that have need of the opposite order. For example, consider a scenario where you need to fix the permissions on a executable, run the executable, and then edit a file that the executable created on the filesystem. This requires an order of files, shellcommands, and the editfiles, the opposite of the above. How does an admin know what action sequence to use? In any even moderately complicated case, it is impractical for an admin to figure this out by hand, and there are some cases where the current two-pass strategy does not work. Here is a more general exposition of the problem. Say we have action types A, B, and D (analogous to cfagent actions such as copy, shellcommands, etc) with specific instances: a (of A), b (of B), and d (of D), where d depends upon b and b depends upon a. Let us also assume that there are further instances of these actions: aa (of A), bb (of B), and dd (of D), where aa depends upon bb, and bb depends upon dd. This is actually a simple case, and it should be relatively obvious what I mean with some pseudo-code: A: any:: a define=a bb:: aa B: a:: b define=b dd:: bb define=bb D: b:: d any:: dd define=dd For simplicity, a < b means that b depends on a. So, encoding the previous example, we obtain two dependency statements: (1) a < b < d (2) dd < bb < aa Now, there are six possible actionsequence values: ABD ADB BAD BDA DAB DBA In reality, cfagent makes two passes over the actionsequence, so we have the following actual actionsequence values: ABDABD (does not satisfy DBA) ADBADB (does not satisfy BDA) BADBAD (does not satisfy DAB) BDABDA (does not satisfy ADB) DABDAB (does not satisfy BAD) DBADBA (does not satisfy ABD) Our example above (a < b < d and dd < bb < aa) is satisfied by the middle four two-pass scenarios, but each two-pass scenario fails to satisfy one possible action ordering. The first and last scenarios fail to satisfy one or the other of the two dependency relationships that we postulated, so in the current implementation it is possible for an admin to create a situation where cfagent will not be able to complete one sequence or the other. You can get around this (if you are aware of the problem) by using class definitions in the actionsequence, such as: control: actionsequence = ( editfiles.daemonconfig shellcommands.daemonconfig files.daemonconfig files.fixexecutable shellcommands.fixexecutable editfiles.fixexecutable ) (Referencing the first example given.) The above is not optimal, but consider if the policy is broken into several per-task fragments that are assembled with import. I think it is clear that if you have N kinds of actions, you need N passes to ensure that all dependencies are resolved. Of course, N passes are only necessary if you actually have instances of all possible orders, which in most cases one will not. cfagent should be able to construct an optimal ordering be examining each action, and noting which classes it is contingent upon and which classes it may define. This is not a proof, so there may be other possible pitfalls that I am not accounting for, but this certainly seems like the way to go, to me. The admin should not have to worry about this sort of thing. Please let me know if anyone can find a flaw in my reasoning or examples. I do not pretend to be a mathematician, so it is quite possible that I got some of the above wrong. :-) I hope it is at least clear. I was going to include some experimental verification of all these things, but this message has gotten too long. Maybe in a future message. _______________________________________________ Help-cfengine mailing list Help-cfengine@gnu.org http://lists.gnu.org/mailman/listinfo/help-cfengine