1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Processes and Executions</title>
</head>
<body>
<h1>Processes and Executions</h1>
In cfengine 2, we have two separate actions:
<pre>
processes
shellcommands
</pre>
In cfengine 3 we have
<pre>
processes
executions
</pre>
Cfengine 2 got this ontology about right intuitively, but not
quite. It allowed "restart" in a process promise which is really a
execution of a file object. This has been changed in cfengine 3 so
that there is a cleaner separation. Let's see why.
Executions are about jobs, services, scripts etc. They are properties
of an executable file. The referring "promising agent" is a file
object. On the other hand a process is a property of a "process
identifier" which is a kernel instantiation, a quite different object
altogether. So it makes sense to say that
<ul>
<li>A "PID agent" (not an executable) promises to send itself a signal, e.g.
<pre>
kill signal pid
</pre>
<li>An "execution agent" promises to start or stop itself with a parameterized specification.
<pre>
exec command argument1 argument2 ...
</pre>
</ul>
Neither the file nor the pid necessarily promise to respond to these activations, but they
are nonetheless physically meaningful phenomena or attributes associated with these objects.
<ul>
<li>Executable files do not listen for signals as they have no active state.
<li>PIDs do not run themselves or stop themselves with new arguments, but they can use signals as they are running.
</ul>
Executions lead to processes for the duration of their lifetime, so these two issues
are related, although the promises themselves are not.
<h2>Services</h2>
A service is an abstraction that requires processes to run and files
to be configured. It makes a lot of sense to wrap services in modular
bundles. Starting and stopping a service can be handled in at least two ways.
Take the web service as an example.
We can start the service by promising an execution of the apache daemon.
Normally this execution does not terminate without intervention. We can
terminate it in one of two ways:
<ul>
<li>Using a process signal, by promising a signal to processes matching a certain pid search
<li>Using an execution of a termination command, e.g. /etc/init.d/apache stop
</ul>
The first case makes sense if we need to qualify the termination by
searching for the processes. The processes section of a cfengine 3
policy includes a control promise to search for matching processes.
If matches are found, signals can be sent to precisely each specific process.
Classes can also be defined, in principle triggering an execution of
the stop script, but then the class refers only to the presence of
matching pids, not to the individual pids concerned. So it becomes
the responsibility of the execution to locate and interact with the
pids necessary.
<h2>Want it running</h2>
How do we say simply that we want a service running
In the agent control promises, we could check each service
individually.
<pre>
bundlesequence => { Update, Service("apache"), Service("nfsd") };
</pre>
or
<pre>
bundlesequence => { Update, @(globals.all_services) };
</pre>
<pre>
bundle agent Service("$(service)")
{
processes:
"$(service)"
process_count => up("$(service)");
executions:
"$daemons[$(service)]"
ifvarclass => "$(service)_up",
args => "$args[$(service)]";
}
An alternative would be self-contained:
<pre>
bundle agent Service
{
vars:
"service" slist => { "apache", "nfsd", "bind" };
processes:
"$(service)"
process_count => up("$(service)");
executions:
"$daemons[$(service)]"
ifvarclass => "$(service)_up",
args => "$args[$(service)]";
}
######################
# Parameterized body
######################
body process_count("$(s)")
{
match_range => "[0,10]";
out_of_range_define => "$(s)_up";
}
</pre>
<h2>A step backwards?</h2>
The cfengine 3 approach might seem like a step backwards from the simple:
<pre>
processes:
"httpd" restart "/etc/init.d/apache restart"
</pre>
However, it allows several improvements.
You can do other things in between stopping and starting the service, like
file editing, or security sweeps.
You can use templates to simplify the syntax in bulk for several process checks
or restarts.
processes:
"$(service.list)"
If you don't want any delay in stopping and starting the service, then
place these promises in a private bundle with nothing in between them.
<hr>
<address><a href="mailto:mark@atlas">Mark Burgess</a></address>
<!-- Created: Thu May 1 12:34:55 CEST 2008 -->
<!-- hhmts start -->
Last modified: Thu May 1 17:06:38 CEST 2008
<!-- hhmts end -->
</body>
</html>
|