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