Difference between revisions of "SME Server:Documentation:Developers Manual:Chapter7"

From SME Server
Jump to navigationJump to search
m (Adjusting header(s))
m (Fixed case in template name)
 
(6 intermediate revisions by 2 users not shown)
Line 29: Line 29:
  
 
This script sets the <var class="LITERAL">ExternalIP</var> value and the <var class="LITERAL">IPAddress</var> property of the <var class="LITERAL">ExternalInterface</var> record in the configuration database to the value provided as a parameter. The <var class="LITERAL">$event</var> parameter is not used in this particular script.
 
This script sets the <var class="LITERAL">ExternalIP</var> value and the <var class="LITERAL">IPAddress</var> property of the <var class="LITERAL">ExternalInterface</var> record in the configuration database to the value provided as a parameter. The <var class="LITERAL">$event</var> parameter is not used in this particular script.
 
+
{{Note box|msg=The two records exist due to an partial migration from simple to complex entries in the configuration database. Setting both values in this script avoids the need to perform database migration in the ip-change event.}}
<div class="NOTE"><blockquote class="NOTE">
+
<div class="SECT2">
 
 
'''Note: '''The two records exist due to an partial migration from simple to complex entries in the configuration database. Setting both values in this script avoids the need to perform database migration in the ip-change event.
 
 
 
</blockquote></div><div class="SECT2">
 
 
----
 
----
  
Line 98: Line 94:
  
 
You should normally link your action scripts in the range <var class="LITERAL">S10</var> to <var class="LITERAL">S80</var> so that they occur after <var class="LITERAL">templates2expand</var> and before <var class="LITERAL">services2adjust</var>.
 
You should normally link your action scripts in the range <var class="LITERAL">S10</var> to <var class="LITERAL">S80</var> so that they occur after <var class="LITERAL">templates2expand</var> and before <var class="LITERAL">services2adjust</var>.
 
+
{{Note box|msg=The <tt>generic_template_expand</tt> action is currently run at <var class="LITERAL">S05</var> and <tt class="FILENAME">adjust-services</tt> is run at <var class="LITERAL">S90</var>. The order of action scripts within an event is subject to change between releases.}}
<div class="NOTE"><blockquote class="NOTE">
+
</div></div><div class="SECT2">
 
 
'''Note: '''The <tt class="FILENAME">generic_template_expand</tt> action is currently run at <var class="LITERAL">S05</var> and <tt class="FILENAME">adjust-services</tt> is run at <var class="LITERAL">S90</var>. The order of action scripts within an event is subject to change between releases.
 
 
 
</blockquote></div></div></div><div class="SECT2">
 
 
----
 
----
  
Line 124: Line 116:
  
 
But how is the action code to know which user was just added? The new username is passed as an argument to the user-create event. This way the action programs triggered by the user-create event have a choice. They can either ignore the username argument and regenerate their output based on the updated list of accounts, or they can pay attention to the username argument, retrieve the rest of the information about the new user from the <tt class="FILENAME">accounts</tt> database, and perform the incremental work to add the user.
 
But how is the action code to know which user was just added? The new username is passed as an argument to the user-create event. This way the action programs triggered by the user-create event have a choice. They can either ignore the username argument and regenerate their output based on the updated list of accounts, or they can pay attention to the username argument, retrieve the rest of the information about the new user from the <tt class="FILENAME">accounts</tt> database, and perform the incremental work to add the user.
 +
{{Note box|msg=Reminder: action scripts should normally take at most two arguments. The first is always the event name. The second optional argument is a key into one of the databases. Events are not function calls.
  
<div class="NOTE"><blockquote class="NOTE">
+
Events are not currently serialized. In most cases overlapping events will not cause issues, but caution should be exercised when events are signalled from programs.}}
 
+
</div><div class="SECT2">
'''Note: '''Reminder: action scripts should normally take at most two arguments. The first is always the event name. The second optional argument is a key into one of the databases. Events are not function calls.
 
 
 
Events are not currently serialized. In most cases overlapping events will not cause issues, but caution should be exercised when events are signalled from programs.
 
 
 
</blockquote></div></div><div class="SECT2">
 
 
----
 
----
  
Line 137: Line 125:
  
 
The table below summarises the key SME Server events and their argument if required. Remember, each action script is always called with the event name as the first argument. The arguments listed in this table are provided as the second argument.
 
The table below summarises the key SME Server events and their argument if required. Remember, each action script is always called with the event name as the first argument. The arguments listed in this table are provided as the second argument.
 
+
{{Note box|msg=Events which are not listed in this table are subject to change and may not appear in future releases of the SME Server.}}
<div class="NOTE"><blockquote class="NOTE">
+
<div class="TABLE">
 
 
'''Note: '''Events which are not listed in this table are subject to change and may not appear in future releases of the SME Server.
 
 
 
</blockquote></div><div class="TABLE">
 
 
 
'''Table 7-1. SME Server standard events'''
 
  
 
{| class="CALSTABLE" border="1"
 
{| class="CALSTABLE" border="1"
 +
|+SME Server standard events
 
! Event
 
! Event
 
! Argument
 
! Argument
 
! Description
 
! Description
 +
|-
 
| bootstrap-console-save
 
| bootstrap-console-save
 
| (none)
 
| (none)

Latest revision as of 08:22, 1 June 2008

Actions and events

Actions

An action is a program, frequently written in a scripting language, which performs a single task. It is typically an encapsulation of a task usually done by a system administrator, such as editing a configuration file or reconfiguring a service. Actions are not called directly; they are always called by signalling an event.

The actions are stored in the /etc/e-smith/events/actions/ directory. These actions are then linked into the relevant events as the same action may need to be performed in more than one event.. To create a new action called myaction you simply create a program to perform the action myaction and save it as /etc/e-smith/events/actions/myaction . Actions can be written in any programming language, although additional platform support is provided for Perl code.

An example action script is set-external-ip which is called when the external IP address changes. Here's the body of that script (at time of writing):

package esmith;

use strict;
use Errno;
use esmith::ConfigDB;

my $db = esmith::ConfigDB->open or die "Couldn't open ConfigDB\n";

my $event = $ARGV[0];
my $newip = $ARGV[1];

$db->set_value('ExternalIP', $newip);
$db->set_prop('ExternalInterface', 'IPAddress', $newip);

exit 0;

This script sets the ExternalIP value and the IPAddress property of the ExternalInterface record in the configuration database to the value provided as a parameter. The $event parameter is not used in this particular script.

Important.png Note:
The two records exist due to an partial migration from simple to complex entries in the configuration database. Setting both values in this script avoids the need to perform database migration in the ip-change event.


Action script parameters

Action scripts are always called with at least one parameter; the name of the current event. Many action scripts, such as set-external-ip , are called with a single additional parameter. This parameter is usually a configuration database key, for example the username being modified or the new IP address.

Action scripts rarely require more than two parameters.The details should be stored in the configuration database(s) and only the key should be passed to the action scripts. Events are not meant to be used as function calls. All configuration details must be stored in the configuration databases and the database key passed as the parameter to the action. This allows other scripts to be added to the event.

Since the SME Server passes the name of the current event as the first parameter, it is often beneficial to write action scripts which are polymorphic based on the event name. For example, the code to create a user and the code to modify an existing user may be only slightly different and may well benefit from being in a single script.


Events

Events are a mechanism which allows the system to trigger a set of actions in response to actual events that happen on the system. When one of the users interfaces modifies the configuration databases, it must signal an event to regenerate the various server application configuration files according to the new configuration. The user interface must never modify configuration files directly.

Each event is associated with a list of actions which should be performed when that event occurs and is defined as a subdirectory of /etc/e-smith/events/ containing symbolic links to the appropriate actions, loosely modelled after the System V init mechanism for starting servers. For example, if you examine the /etc/e-smith/events/ip-change directory:

lrwxrwxrwx  1 root root   26  S15set-external-ip -> ../actions/set-external-ip*
lrwxrwxrwx  1 root root   21  S85update-dns -> ../actions/update-dns*
drwxr-xr-x  2 root root 4096  services2adjust/
drwxr-xr-x  5 root root 4096  templates2expand/

The symbolic links are given prefixes such as S15, S85, etc. to specify the order in which the actions should be executed in a similar manner to the System V init mechanism.

You can change the actions performed by an event by changing the links in the event directory. You can also create a new event by creating another subdirectory of /etc/e-smith/events/.


Implicit actions: services2adjust and templates2expand

Most events contain two common tasks: expanding various templates and adjusting (e.g. restarting) the relevant services. For this reason, two implicit actions are included in all events. These implicit actions mean that additional code does not need to be written to perform these common tasks. The implicit actions are represented by entries in the services2adjust/ and templates2expand/ subdirectories.


services2adjust

The services2adjust/ directory contains links mapping a specific service to the action to perform on that service. For example, if signalling the event in question requires that the ntpd service is restarted, you simply include the link ntpd -> restart in the services2adjust directory. The implicit action services2adjust would then restart the ntpd service. As an example, the services2adjust/ directory for the ip-change event is shown below:

lrwxrwxrwx  1 root root 6  masq -> adjust
lrwxrwxrwx  1 root root 7  ntpd -> restart
lrwxrwxrwx  1 root root 7  pptpd -> sigterm
lrwxrwxrwx  1 root root 6  qmail -> sighup
lrwxrwxrwx  1 root root 7  tinydns -> sigusr2

templates2expand

The templates2expand/ directory contains a list of the configuration files which need to be regenerated from their templates. This list consists of a collection of empty files with the same file name as the configuration file to be expanded and in a heirarchy mirroring their location on the system. For example, to expand templates for the /etc/samba/smb.conf configuration file, simply include the empty file etc/samba/smb.conf in the templates2expand/ directory of the relevant event(s). For more detail, see the Section called Mapping templates to events: templates2expand in Chapter 8.


Order of implicit actions

The implicit actions are implemented by inserting the action script generic_template_expand early in the list of actions to be run in an event and the adjust-services action near the end of the list.

You should normally link your action scripts in the range S10 to S80 so that they occur after templates2expand and before services2adjust.

Important.png Note:
The generic_template_expand action is currently run at S05 and adjust-services is run at S90. The order of action scripts within an event is subject to change between releases.


Signalling events

The signal-event program takes an event name as an argument, and executes all of the actions in that event, providing the event name as the first parameter and directing all output to the system log. It works by listing the entries in the event directory and executing them in sequence. So for example, the command:

signal-event console-save

will perform all the actions associated with the console-save event, which is defined by the contents of the /etc/e-smith/events/console-save/ directory. This is exactly what the console user interface does when you select save at the end of the console configuration wizard.


Events with arguments

So far we have described the following general principle throughout the SME Server; changes are made by altering the configuration files, then signalling events. The actions triggered by each event typically regenerate entire configuration files, taking into account the latest configuration information.

However, some changes are best made incrementally. For example, consider the user-create event. One of its actions updates the LDAP directory, which it could do by deleting all of the users and recreating them based on the updated accounts database. However, this is inefficient and would lose any additional LDAP attributes which may have been stored. It would be better to simply add the new user incrementally, using the default LDAP schema.

But how is the action code to know which user was just added? The new username is passed as an argument to the user-create event. This way the action programs triggered by the user-create event have a choice. They can either ignore the username argument and regenerate their output based on the updated list of accounts, or they can pay attention to the username argument, retrieve the rest of the information about the new user from the accounts database, and perform the incremental work to add the user.

Important.png Note:
Reminder: action scripts should normally take at most two arguments. The first is always the event name. The second optional argument is a key into one of the databases. Events are not function calls.

Events are not currently serialized. In most cases overlapping events will not cause issues, but caution should be exercised when events are signalled from programs.



Standard events and their arguments

The table below summarises the key SME Server events and their argument if required. Remember, each action script is always called with the event name as the first argument. The arguments listed in this table are provided as the second argument.

Important.png Note:
Events which are not listed in this table are subject to change and may not appear in future releases of the SME Server.

SME Server standard events
Event Argument Description
bootstrap-console-save (none) Expands all templates in the system. It is a requirement that all templates are correct after a combination of post-upgrade/reboot. Called after the initial console wizard, after system upgrades, and as part of a reconfiguration reboot.
console-save (none) Expands templates and reconfigures services which can be changed from the text-mode console and which do not require a reboot. Services which do require a reboot for configuration will be handled by bootstrap-console-save. The console-save event is not a general "reconfigure everything" event.
email-update (none) Reconfigures services listed on the e-mail panel.
group-create, group-delete, group-modify Group - key into accounts database Called when a group is created/deleted/modified.
halt (none) Called when the system is being shutdown prior to power off.
host-create, host-delete, host-modify Host - key into hosts database Called when a host is created, deleted or modified.
ibay-create, ibay-delete, ibay-modify Ibay - key into accounts database Called when an information bay is created/deleted/modified.
ip-change New external IP address Called when the external IP address changes, e.g. through a new PPPoE connection or DHCP lease.
local (none) Called after each reboot. Customisations which would normally require modification of the /etc/rc.local file should instead be installed as individual scripts in the /etc/e-smith/events/local/ event directory.
network-create, network-delete Network - key into networks database Called when a local network is created or deleted.
password-modify User - key into accounts database Called when a user password is modified, including when the account is unlocked.
post-upgrade (and post-install) (none) Called as final step of the CD upgrade (install). This event must be immediately followed by a reboot. The bootstrap-console-save event is then called after the reboot to complete the reconfiguration. The only changes which should occur in this event are ones which must be performed prior to the reboot (e.g. configuring the boot loader). The post-install event is only called once, from the CD installer.
pre-backup, post-backup Cause - type of backup being performed (e.g. "tape") The pre-backup event creates consistent system state for the backup. For example, it creates an ASCII dump of the MySQL databases. If the pre-backup event fails, the backup is not run. The post-backup is called if the backup is successful and removes the state files generated by pre-backup.
pseudonym-create, pseudonym-delete, pseudonym-modify Pseudonym - key into accounts database Called when a pseudonym is created/deleted/modified.
reboot (none) Called when the system is being shutdown prior to a reboot.
remoteaccess-update (none) Reconfigures services listed on the Remote Access panel and updates the firewall rules for all services.
user-create, user-delete, user-modify User - key into accounts database Called when a user is created/deleted/modified.
user-lock User - key into accounts database Called when a user account is locked.

Handling deletions

When adding a user, the user is created in the accounts database, and various actions, such as creating the Linux account, are performed in the user-create event. However, when deleting a user, we want to maintain the accounts database entry for as long as possible, in case there is information which the actions in the user-delete event might need in order to cleanly delete the users.

The SME Server convention for handling deletions is:

  • Change the type of the entry to mark it as being in the process of being deleted e.g. a user entry becomes a user-deleted entry.
  • Signal the relevant deletion event - e.g. user-delete
  • Remove the entry from the database, but only if the event succeeds.

With this approach, the action scripts can decide whether to ignore the user-deleted entries when performing their tasks.


Event logs

All events, and all actions run by the event, are logged to the messages system log. Here is an example action log, which has been formatted onto multiple lines to enhance readability:

Feb  2 13:22:33 gsxdev1 esmith::event[4525]:
  S65sshd-conf=action|
  Event|remoteaccess-update|
  Action|S65sshd-conf|
  Start|1138846952 730480|
  End|1138846953 66768|
  Elapsed|0.336288

From this single log, we can see the action script name, which event it was called in, when it started, ended and how long it took (0.34 seconds). Now, let's add an action script which always fails and signal the event again:

Feb  2 16:11:54 gsxdev1 esmith::event[4787]:
  S99false=action|
  Event|remoteaccess-update|
  Action|S99false|
  Start|1138857114 58910|
  End|1138857114 81920|
  Elapsed|0.02301|
  Status|256

Note that this log has a new field Status, which is added if the action script returns a false (non-zero) exit status. Suppressing the Status field when it is zero (success) makes it much easier to find failed actions in the logs.


Failed events

If an action script fails, the entire event fails. The other actions scripts in the event are run, but the whole event is marked as having failed.

By convention, if a delete event fails, the user interface does not delete the entry from the relevant database. So, if the user-delete event fails, a "stray" user-deleted entry will appear in the accounts database. The event logs with Status properties can be matched with the user-deleted entries to determine which action script failed so it can be corrected in the future. This user-deleted entry will also block the creation of another account with that name until the issue is corrected.