r4198 add chdir to make it work again
[racktables] / syncdomain.php
1 #!/usr/local/bin/php
2 <?php
3
4 $script_mode = TRUE;
5 chdir ('wwwroot');
6 require 'inc/init.php';
7
8 function usage()
9 {
10 echo "Usage: <this file> <options>\n";
11 echo "\t\t--vdid=<VLAN domain ID>\n";
12 echo "\t\t--mode=pull\n";
13 echo "\t\t--mode=pullall\n";
14 echo "\t\t--mode=push\n";
15 echo "\t\t[--max=<max_to_do>]\n";
16 echo "\t\t[--verbose]\n";
17 exit (1);
18 }
19
20 $options = getopt ('', array ('vdid:', 'max::', 'mode:', 'verbose'));
21 if (!array_key_exists ('vdid', $options) or !array_key_exists ('mode', $options))
22 usage();
23
24 switch ($options['mode'])
25 {
26 case 'pullall':
27 $do_push = FALSE;
28 break;
29 case 'pull':
30 $do_push = FALSE;
31 break;
32 case 'push':
33 $do_push = TRUE;
34 break;
35 default:
36 usage();
37 }
38
39 $max = array_key_exists ('max', $options) ? $options['max'] : 0;
40 $verbose = array_key_exists ('verbose', $options);
41
42 try
43 {
44 $mydomain = getVLANDomain ($options['vdid']);
45 }
46 catch (RackTablesError $e)
47 {
48 echo "Cannot load domain data with ID ${options['vdid']}\n";
49 echo $e->getMessage() . "\n";
50 exit (1);
51 }
52
53 $todo = array
54 (
55 'pull' => array ('sync_ready', 'resync_ready'),
56 'push' => array ('sync_ready'),
57 'pullall' => array ('sync_ready', 'resync_ready', 'sync_aging', 'resync_aging', 'done'),
58 );
59
60 $filename = '/var/tmp/RackTables-syncdomain-' . $options['vdid'] . '.pid';
61 if (FALSE === $fp = @fopen ($filename, 'x+'))
62 {
63 if (FALSE === $pidfile_mtime = filemtime ($filename))
64 {
65 echo "Failed to obtain mtime of ${filename}\n";
66 exit (1);
67 }
68 $current_time = time();
69 if ($current_time < $pidfile_mtime)
70 {
71 echo "Warning: pidfile ${filename} mtime is in future!\n";
72 exit (1);
73 }
74 // don't indicate failure unless the pidfile is 15 minutes or more old
75 if ($current_time < $pidfile_mtime + 15 * 60)
76 exit (0);
77 echo "Failed to lock ${filename}, already locked by PID " . mb_substr (file_get_contents ($filename), 0, 6) . "\n";
78 exit (1);
79 }
80
81 ftruncate ($fp, 0);
82 fwrite ($fp, getmypid() . "\n");
83 fclose ($fp);
84
85 // fetch all the needed data from DB (preparing for DB connection loss)
86 $switch_queue = array();
87 foreach ($mydomain['switchlist'] as $switch)
88 if (in_array (detectVLANSwitchQueue (getVLANSwitchInfo ($switch['object_id'])), $todo[$options['mode']]))
89 $switch_queue[] = spotEntity ('object', $switch['object_id']);
90
91 // YOU SHOULD NOT USE DB FUNCTIONS BELOW IN THE PARENT PROCESS
92 // THE PARENT'S DB CONNECTION IS LOST DUE TO RECONNECTING IN THE CHILD
93 $fork_slots = getConfigVar ('SYNCDOMAIN_MAX_PROCESSES');
94 $do_fork = ($fork_slots > 1) and extension_loaded ('pcntl');
95 if ($fork_slots > 1 and ! $do_fork)
96 throw new RackTablesError ('PHP extension \'pcntl\' not found, can not use childs', RackTablesError::MISCONFIGURED);
97 $switches_working = 0;
98 $switchesdone = 0;
99 foreach ($switch_queue as $object)
100 {
101 if ($do_fork)
102 {
103 // wait for the next free slot
104 while ($fork_slots <= $switches_working)
105 {
106 pcntl_waitpid (-1, $wait_status);
107 --$switches_working;
108 }
109 $i_am_child = (0 === $fork_res = pcntl_fork());
110 }
111 if (! $do_fork or $i_am_child)
112 {
113 try
114 {
115 // make a separate DB connection for correct concurrent transactions handling
116 if ($i_am_child)
117 connectDB();
118 $portsdone = exec8021QDeploy ($object['id'], $do_push);
119 if ($portsdone or $verbose)
120 echo "Done '${object['dname']}': ${portsdone}\n";
121 }
122 catch (RackTablesError $e)
123 {
124 echo "FAILED '${object['dname']}': " . $e->getMessage() . "\n";
125 }
126 if ($i_am_child)
127 exit (0);
128 }
129 if (isset ($fork_res) and $fork_res > 0)
130 ++$switches_working;
131
132 if (++$switchesdone == $max)
133 {
134 if ($verbose)
135 echo "Maximum of ${max} items reached, terminating\n";
136 break;
137 }
138 }
139
140 // wait for all childs to exit
141 while ($switches_working > 0)
142 {
143 --$switches_working;
144 pcntl_waitpid (-1, $wait_status);
145 }
146
147 if (FALSE === unlink ($filename))
148 {
149 echo "Failed removing pidfile ${filename}\n";
150 exit (1);
151 }
152 exit (0);
153 ?>