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