r4868 fix IPv4RS sample data
[racktables] / scripts / syncdomain.php
CommitLineData
46f2c279
DO
1#!/usr/local/bin/php
2<?php
3
4$script_mode = TRUE;
5require 'inc/init.php';
6
7function 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
ac936aaa
DO
19function print_message_line($text)
20{
21 echo gmdate (DATE_RFC1123) . ": ${text}\n";
22}
23
0eb16817 24$options = getopt ('', array ('vdid:', 'max::', 'mode:', 'verbose'));
f1cdc9f1 25if (!array_key_exists ('mode', $options))
46f2c279
DO
26 usage();
27
28switch ($options['mode'])
29{
30case 'pullall':
31 $do_push = FALSE;
32 break;
33case 'pull':
34 $do_push = FALSE;
35 break;
36case 'push':
37 $do_push = TRUE;
38 break;
39default:
40 usage();
41}
42
43$max = array_key_exists ('max', $options) ? $options['max'] : 0;
0eb16817 44$verbose = array_key_exists ('verbose', $options);
46f2c279 45
f1cdc9f1
AA
46$switch_list = array();
47if (! isset ($options['vdid']))
48 $switch_list = getVLANSwitches();
49else
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 {
ac936aaa
DO
58 print_message_line ("Cannot load domain data with ID ${options['vdid']}");
59 print_message_line ($e->getMessage());
f1cdc9f1
AA
60 exit (1);
61 }
46f2c279
DO
62
63$todo = array
64(
611b5e46 65 'pull' => array ('sync_ready', 'resync_ready'),
089e6bfe 66 'push' => array ('sync_ready', 'resync_ready'),
611b5e46 67 'pullall' => array ('sync_ready', 'resync_ready', 'sync_aging', 'resync_aging', 'done'),
46f2c279
DO
68);
69
f1cdc9f1
AA
70$domain_key = isset ($options['vdid']) ? $options['vdid'] : 0;
71$filename = '/var/tmp/RackTables-syncdomain-' . $domain_key . '.pid';
fc81b88e
DO
72if (FALSE === $fp = @fopen ($filename, 'x+'))
73{
a50d3f2b
DO
74 if (FALSE === $pidfile_mtime = filemtime ($filename))
75 {
ac936aaa 76 print_message_line ("Failed to obtain mtime of ${filename}");
a50d3f2b
DO
77 exit (1);
78 }
79 $current_time = time();
80 if ($current_time < $pidfile_mtime)
81 {
ac936aaa 82 print_message_line ("Warning: pidfile ${filename} mtime is in future!");
a50d3f2b
DO
83 exit (1);
84 }
85 // don't indicate failure unless the pidfile is 15 minutes or more old
1c638ec1 86 if ($current_time < $pidfile_mtime + 15 * 60)
a50d3f2b 87 exit (0);
ac936aaa 88 print_message_line ("Failed to lock ${filename}, already locked by PID " . mb_substr (file_get_contents ($filename), 0, 6));
fc81b88e
DO
89 exit (1);
90}
91
92ftruncate ($fp, 0);
93fwrite ($fp, getmypid() . "\n");
94fclose ($fp);
95
61e79d63
AA
96// fetch all the needed data from DB (preparing for DB connection loss)
97$switch_queue = array();
f1cdc9f1
AA
98foreach ($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 }
61e79d63
AA
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');
110if ($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;
114foreach ($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)
46f2c279 127 {
647635ad
DO
128 try
129 {
61e79d63
AA
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);
647635ad 134 if ($portsdone or $verbose)
ac936aaa 135 print_message_line ("Done '${object['dname']}': ${portsdone}");
647635ad
DO
136 }
137 catch (RackTablesError $e)
138 {
ac936aaa 139 print_message_line ("FAILED '${object['dname']}': " . $e->getMessage());
647635ad 140 }
61e79d63
AA
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)
ac936aaa 150 print_message_line ("Maximum of ${max} items reached, terminating");
61e79d63 151 break;
46f2c279 152 }
61e79d63
AA
153}
154
155// wait for all childs to exit
156while ($switches_working > 0)
157{
158 --$switches_working;
159 pcntl_waitpid (-1, $wait_status);
160}
46f2c279 161
fc81b88e
DO
162if (FALSE === unlink ($filename))
163{
ac936aaa 164 print_message_line ("Failed removing pidfile ${filename}");
fc81b88e
DO
165 exit (1);
166}
46f2c279
DO
167exit (0);
168?>