4 * Small and fast system action trigger
6 * Copyright (C) 2014 Inria (Sylvain Beucler)
8 * This file is part of FusionForge. FusionForge is free software;
9 * you can redistribute it and/or modify it under the terms of the
10 * GNU General Public License as published by the Free Software
11 * Foundation; either version 2 of the Licence, or (at your option)
14 * FusionForge is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 //putenv('FUSIONFORGE_NO_PLUGINS=true');
25 //putenv('FUSIONFORGE_NO_DB=true');
27 require (dirname(__FILE__).'/../common/include/env.inc.php');
28 require_once $gfcommon.'include/pre.php';
29 require_once $gfcommon.'include/cron_utils.php';
31 // Locking: for a single script
32 // flock() locks are automatically lost on program termination, however
33 // that happened (clean, segfault...)
34 $lock = null; // global, or auto-closed by PHP and we lose the lock!
35 function AcquireReplicationLock($script) {
36 // Script lock: http://perl.plover.com/yak/flock/samples/slide006.html
38 $lock = fopen($script, 'r') or die("Failed to ask lock.\n");
40 if (!flock($lock, LOCK_EX | LOCK_NB)) {
41 die("There's a lock for '$script', exiting\n");
45 // Invalidate users/groups cache e.g. when a user is added to a group
46 // Special-case in 'publish-subscribe' mode
47 function usergroups_sync() {
48 global $usergroups_lastsync;
49 $res = db_query_params("SELECT MAX(last_modified_date) AS lastmodified FROM nss_usergroups");
50 $row = db_fetch_array($res);
51 if ($row['lastmodified'] > $usergroups_lastsync) {
53 $hook_params = array();
54 plugin_hook("usergroups_sync", $hook_params);
55 $usergroups_lastsync = time();
59 function sysaction_get_script($plugin_id, $sysaction_type_id) {
62 if ($plugin_id == null) {
63 if (isset($cron_arr[$sysaction_type_id]))
64 return forge_get_config('source_path')
65 .'/cronjobs/'.$cron_arr[$sysaction_type_id];
67 if (isset($plugins[$plugin_id])) {
68 $plugin = $pm->GetPluginObject($plugins[$plugin_id]);
69 if (isset($plugin->sysaction_types[$sysaction_type_id]))
70 return forge_get_config('plugins_path')."/".$plugin->GetName()
71 ."/cronjobs/".$plugin->sysaction_types[$sysaction_type_id];
79 $shortopts = "v"; // enable verbose mode
81 $options = getopt($shortopts, $longopts);
82 if ($options === false) { // doesn't work, PHP returns ambiguous array() on error..
83 print "Usage: {$argv[0]} [-v]\n";
87 if (isset($options['v'])) {
88 print "verbose mode ON\n";
98 // Hack to reopen stdin/stdout/stderr, order is important
99 // https://andytson.com/blog/2010/05/daemonising-a-php-cli-script-on-a-posix-system/
103 $ff_stdin = fopen('/dev/null', 'r');
104 $ff_stdout = fopen('/dev/null', 'w');
105 $ff_stderr = fopen('php://stdout', 'w');
107 // We could fork & continue in the background too, but then we'd have
108 // to manage the PID file as well - best leave this to the init script
111 $pm = plugin_manager_get_object();
112 $plugins = $pm->GetPlugins();
116 // Deal with pending requests
117 $res = db_query_params("SELECT * FROM sysactionsq WHERE status=$1"
118 . " ORDER BY sysactionsq_id LIMIT 1", array('TODO'));
119 if (!$res && !db_connection_status())
121 while ($arr = db_fetch_array($res)) {
123 $script = sysaction_get_script($arr['plugin_id'], $arr['sysaction_type_id']);
124 if (!file_exists($script))
125 // Not installed on this node, skipping
127 if (!is_executable($script)) {
128 db_query_params("UPDATE sysactionsq SET status=$1, error_message=$2"
129 . " WHERE sysactionsq_id=$3",
131 "Cron job {$arr['plugin_id']}/{$arr['sysaction_type_id']}"
132 . " '$script' not executable.\n",
133 $arr['sysactionsq_id']));
136 db_query_params("UPDATE sysactionsq SET status=$1 WHERE sysactionsq_id=$2",
137 array('WIP', $arr['sysactionsq_id']));
138 AcquireReplicationLock($script);
140 if ($verbose) print "Running: $script... ";
141 system("$script\n", $ret);
143 if ($verbose) print "DONE\n";
144 db_query_params("UPDATE sysactionsq SET status=$1 WHERE sysactionsq_id=$2",
145 array('DONE', $arr['sysactionsq_id']));
147 if ($verbose) print "ERROR\n";
148 db_query_params("UPDATE sysactionsq SET status=$1 WHERE sysactionsq_id=$2",
149 array('ERROR', $arr['sysactionsq_id']));
160 // c-file-style: "bsd"