/* action operations */ ham_action_t *ham_action_restart(ham_condition_t *chdl, const char *aname, const char *path, unsigned flags); ham_action_t *ham_action_execute(ham_condition_t *chdl, const char *aname, const char *path, unsigned flags); ham_action_t *ham_action_waitfor(ham_condition_t *chdl, const char *aname, const char *path, int delay, unsigned flags); ham_action_t *ham_action_notify_pulse(ham_condition_t *chdl, const char *aname, int nd, int topid, int chid, int pulsecode, int value, unsigned flags); ham_action_t *ham_action_notify_signal(ham_condition_t *chdl, const char *aname, int nd, pid_t topid, int signum, int code, int value, unsigned flags); ham_action_t *ham_action_notify_pulse_node(ham_condition_t *chdl, const char *aname, const char *nodename, int topid, int chid, int pulsecode, int value, unsigned flags); ham_action_t *ham_action_notify_signal_node(ham_condition_t *chdl, const char *aname, const char *nodename, pid_t topid, int signum, int code, int value, unsigned flags); ham_action_t *ham_action_heartbeat_healthy(ham_condition_t *chdl, const char *aname, unsigned flags); ham_action_t *ham_action_log(ham_condition_t *chdl, const char *aname, const char *msg, unsigned attachprefix, int verbosity, unsigned flags); /* remove an action */ int ham_action_remove(ham_action_t *ahdl, unsigned flags);
As mentioned earlier, a HAM currently supports several different types of action functions, but note that you can add your own action functions to suit your particular HA application.
This executes a command line as specified in the parameters. The command line must contain the FULL path to the executable along with all parameters to be passed to it. The command line is in turn passed onto a spawn command by a HAM to create a new process that will execute the command.
You'll find execute actions useful when you need to set up a multistage recovery. For example, if fs-nfs2 dies and is restarted, the ham_action_execute() function lets you remount any directories that are required after fs-nfs2 is restarted.
You can have an execute action take place immediately by setting the HACTIONDONOW flag. Again, this is useful in startup situations when an entity is created in many stages.
Note that HACTIONDONOW is ignored for waitfor actions. So in order to insert delays into a sequence of actions flagged HACTIONDONOW, you'll need to insert the delays in the client program (between calls to ham_action*()).
The ham_action_waitfor() call takes as an argument a path component, which can be used to wait for a specific name to appear in the name space. If path is NULL, the waitfor is for exactly delay msecs. But if path is specified, the waitfor is for either delay msecs or until path appears in the namespace, whichever occurs earlier. Note that the delay when a pathname is specified is in integral multiples of 100 msecs.
If a pathname is specified, the delays will be the closest integral multiple of 100 msecs, rounding up. A delay of 0 effectively disables the waitfor, making the pathname specification redundant.
The ham_action_notify_signal() sends an appropriate realtime signal with a value to the pid that requests it.
Actions can persist across a restart if the entity is restarted. Similarly, conditions can also be set to persist (i.e., you can rearm them) after a restart of the entity. You can do this by ORing HREARMAFTERRESTART into the flags argument to either the ham_condition() call or to the appropriate action statement.
If a condition persists when an entity is restarted, each individual action is checked to see if it also persists. Actions that needn't be rearmed are performed once and removed. Any actions that fail are also removed, even if they're set to be rearmed.
If a condition isn't marked as rearmed, then all actions under it are automatically removed, since the actions are associated only with the condition and can't be retained if the condition no longer exists.
The persistence of conditions and actions across a restart depends on the restart of the entity itself. So if the entity isn't restarted (i.e., there's no ACTION_RESTART or the ACTION_RESTART fails for some reason), then the entity is removed, along with all conditions and actions associated with the entity as well.