Projet

Général

Profil

Télécharger (11,2 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / gmirror.inc @ 340ce958

1
<?php
2
/*
3
	gmirror.inc
4
	Copyright (C) 2009-2014 Jim Pingle
5

    
6
	Redistribution and use in source and binary forms, with or without
7
	modification, are permitted provided that the following conditions are met:
8

    
9
	1. Redistributions of source code must retain the above copyright notice,
10
	this list of conditions and the following disclaimer.
11

    
12
	2. Redistributions in binary form must reproduce the above copyright
13
	notice, this list of conditions and the following disclaimer in the
14
	documentation and/or other materials provided with the distribution.
15

    
16
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17
	INClUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
20
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
	POSSIBILITY OF SUCH DAMAGE.
26
*/
27

    
28
global $balance_methods;
29
$balance_methods = array("load", "prefer", "round-robin", "split");
30

    
31
/* Create a status array for each mirror and its disk components. */
32
function gmirror_get_status() {
33
	$status = "";
34
	exec("/sbin/gmirror status -s", $status);
35
	$mirrors = array();
36

    
37
	/* Empty output = no mirrors found */
38
	if (count($status) > 0) {
39
		/* Loop through gmirror status output. */
40
		foreach ($status as $line) {
41
			/* Split the line by whitespace */
42
			$all = preg_split("/[\s\t]+/", trim($line), 3);
43
			if (count($all) == 3) {
44
				/* If there are three items on a line, it is mirror name, status, and component */
45
				$currentmirror = basename($all[0]);
46
				$mirrors[$currentmirror]['name'] = basename($all[0]);
47
				$mirrors[$currentmirror]['status'] = $all[1];
48
				if (!is_array($mirrors[$currentmirror]['components']))
49
					$mirrors[$currentmirror]['components'] = array();
50
				$mirrors[$currentmirror]['components'][] = $all[2];
51
			}
52
		}
53
	}
54
	/* Return an hash of mirrors and components */	
55
	return $mirrors;
56
}
57

    
58
/* Get only status word for a single mirror. */
59
function gmirror_get_status_single($mirror) {
60
	$status = "";
61
	$mirror_status = gmirror_get_status();
62
	var_dump($mirror_status);
63
	return $mirror_status[$mirror]['status'];
64
}
65

    
66
/* Generate an HTML formatted status for mirrors and disks in a small format for the widget */
67
function gmirror_html_status() {
68
	$mirrors = gmirror_get_status();
69
	$output = "";
70
	if (count($mirrors) > 0) {
71
		$output .= "<tr>\n";
72
		$output .= "<td width=\"40%\" class=\"vncellt\">Name</td>\n";
73
		$output .= "<td width=\"40%\" class=\"vncellt\">Status</td>\n";
74
		$output .= "<td width=\"20%\" class=\"vncellt\">Component</td>\n";
75
		$output .= "</tr>\n";
76
		foreach ($mirrors as $mirror => $name) {
77
			$components = count($name["components"]);
78
			$output .= "<tr>\n";
79
			$output .= "<td width=\"40%\" rowspan=\"{$components}\" class=\"listr\">{$name['name']}</td>\n";
80
			$output .= "<td width=\"40%\" rowspan=\"{$components}\" class=\"listr\">{$name['status']}</td>\n";
81
			$output .= "<td width=\"20%\" class=\"listr\">{$name['components'][0]}</td>\n";
82
			$output .= "</tr>\n";
83
			if (count($name["components"]) > 1) {
84
				$morecomponents = array_slice($name["components"], 1);
85
				foreach ($morecomponents as $component) {
86
					$output .= "<tr>\n";
87
					$output .= "<td width=\"20%\" class=\"listr\">{$component}</td>\n";
88
					$output .= "</tr>\n";
89
				}
90
			}
91
		}
92
	} else {
93
		$output .= "<tr><td colspan=\"3\" class=\"listr\">No Mirrors Found</td></tr>\n";
94
	}
95
	// $output .= "<tr><td colspan=\"3\" class=\"listr\">Updated at " . date("F j, Y, g:i:s a") . "</td></tr>\n";
96
	return $output;
97
}
98

    
99
/* List all disks in the system (potential gmirror targets) */
100
function gmirror_get_disks() {
101
	$disklist = "";
102
	/* Get a list of disks in a scriptable way, exclude optical drives */
103
	exec("/sbin/geom disk status -s | /usr/bin/grep -v '[[:blank:]]*cd[[:digit:]]*' | /usr/bin/awk '{print $1;}'", $disklist);
104
	return $disklist;
105
}
106

    
107
/* List all potential gmirror consumers */
108
function gmirror_get_unused_consumers() {
109
	$consumerlist = "";
110
	/* Get a list of consumers, exclude existing mirrors and diskid entries */
111
	exec("/sbin/geom part status -s | /usr/bin/egrep -v '(mirror|diskid)' | /usr/bin/awk '{print $1, $3;}'", $consumerlist);
112
	$all_consumers = array();
113
	foreach ($consumerlist as $cl) {
114
		$parts = explode(" ", $cl);
115
		foreach ($parts as $part)
116
			$all_consumers[] = $part;
117
	}
118
	return $all_consumers;
119
}
120

    
121
/* List all existing geom mirrors */
122
function gmirror_get_mirrors() {
123
	$mirrorlist = "";
124
	exec("/sbin/gmirror list | /usr/bin/grep '^Geom name:' | /usr/bin/awk '{print $3;}'", $mirrorlist);
125
	return $mirrorlist;
126
}
127

    
128

    
129
/* List all consumers for a given mirror */
130
function gmirror_get_consumers_in_mirror($mirror) {
131
	if (!is_valid_mirror($mirror))
132
		return array();
133

    
134
	$consumers = array();
135
	exec("/sbin/gmirror status -s " . escapeshellarg($mirror) . " | /usr/bin/awk '{print $3;}'", $consumers);
136
	return $consumers;
137
}
138

    
139
/* Test if a given consumer is a member of an existing mirror */
140
function is_consumer_in_mirror($consumer, $mirror) {
141
	if (!is_valid_consumer($consumer) || !is_valid_mirror($mirror))
142
		return false;
143

    
144
	$mirrorconsumers = gmirror_get_consumers_in_mirror($mirror);
145
	return in_array(basename($consumer), $mirrorconsumers);
146
}
147

    
148
/* Test if a mirror exists */
149
function is_valid_mirror($mirror) {
150
	$mirrors = gmirror_get_mirrors();
151
	return in_array($mirror, $mirrors);
152
}
153

    
154
/* Test if a disk is valid/exists */
155
function is_valid_disk($disk) {
156
	$adisks = gmirror_get_disks();
157
	return in_array(basename($disk), $adisks);
158
}
159

    
160
/* Test if a consumer is valid and in use in a mirror */
161
function is_consumer_used($consumer) {
162
	$found = false;
163
	$mirrors = gmirror_get_mirrors();
164
	foreach ($mirrors as $mirror) {
165
		$consumers = gmirror_get_consumers_in_mirror($mirror);
166
		if (in_array($consumer, $consumers))
167
			return true;
168
	}
169
	return false;
170
}
171

    
172
/* Test if a consumer is valid and not in use */
173
function is_consumer_unused($consumer) {
174
	$consumers = gmirror_get_unused_consumers();
175
	return in_array($consumer, $consumers);
176
}
177

    
178
/* Test if a consumer is valid (either a disk or partition) */
179
function is_valid_consumer($consumer) {
180
	return (is_consumer_unused($consumer) || is_consumer_used($consumer));
181
}
182

    
183
/* Remove all disconnected drives from a mirror */
184
function gmirror_forget_disconnected($mirror) {
185
	if (!is_valid_mirror($mirror))
186
		return false;
187
	return mwexec("/sbin/gmirror forget " . escapeshellarg($mirror));
188
}
189

    
190
/* Insert another consumer into a mirror */
191
function gmirror_insert_consumer($mirror, $consumer) {
192
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer))
193
		return false;
194
	return mwexec("/sbin/gmirror insert " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
195
}
196

    
197
/* Remove consumer from a mirror and clear its metadata */
198
function gmirror_remove_consumer($mirror, $consumer) {
199
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer))
200
		return false;
201
	return mwexec("/sbin/gmirror remove " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
202
}
203

    
204
/* Wipe geom info from drive (if mirror is not running) */
205
function gmirror_clear_consumer($consumer) {
206
	if (!is_valid_consumer($consumer))
207
		return false;
208
	return mwexec("/sbin/gmirror clear " . escapeshellarg($consumer));
209
}
210

    
211
/* Find the balance method used by a given mirror */
212
function gmirror_get_mirror_balance($mirror) {
213
	if (!is_valid_mirror($mirror))
214
		return false;
215
	$balancemethod = "";
216
	exec("/sbin/gmirror list " . escapeshellarg($mirror) . " | /usr/bin/grep '^Balance:' | /usr/bin/awk '{print $2;}'", $balancemethod);
217
	return $balancemethod[0];
218
}
219

    
220
/* Change balance algorithm of the mirror */
221
function gmirror_configure_balance($mirror, $balancemethod) {
222
	global $balance_methods;
223
	if (!is_valid_mirror($mirror) || !in_array($balancemethod, $balance_methods))
224
		return false;
225
	return mwexec("/sbin/gmirror configure -b " . escapeshellarg($balancemethod) . " " . escapeshellarg($mirror));
226
}
227

    
228
/* Force a mirror member to rebuild */
229
function gmirror_force_rebuild($mirror, $consumer) {
230
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer))
231
		return false;
232
	return mwexec("/sbin/gmirror rebuild " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
233
}
234

    
235
/* Show all metadata on the physical consumer */
236
function gmirror_get_consumer_metadata($consumer) {
237
	if (!is_valid_consumer($consumer))
238
		return array();
239
	$output = "";
240
	exec("/sbin/gmirror dump " . escapeshellarg($consumer), $output);
241
	return array_map('trim', $output);
242
}
243

    
244
/* Test if a consumer has metadata, indicating it is a member of a mirror (active or inactive) */
245
function gmirror_consumer_has_metadata($consumer) {
246
	return (count(gmirror_get_consumer_metadata($consumer)) > 0);
247
}
248

    
249
/* Find the mirror to which this consumer belongs */
250
function gmirror_get_consumer_metadata_mirror($consumer) {
251
	if (!is_valid_consumer($consumer))
252
		return array();
253
	$metadata = gmirror_get_consumer_metadata($consumer);
254
	foreach ($metadata as $line) {
255
		if (substr($line, 0, 5) == "name:") {
256
			list ($key, $value) = explode(":", $line, 2);
257
			return trim($value);
258
		}
259
	}
260
}
261

    
262
/* Deactivate consumer, removing it from service in the mirror, but leave metadata intact */
263
function gmirror_deactivate_consumer($mirror, $consumer) {
264
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer))
265
		return false;
266
	return mwexec("/sbin/gmirror deactivate " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
267
}
268

    
269
/* Reactivate a deactivated consumer */
270
function gmirror_activate_consumer($mirror, $consumer) {
271
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer))
272
		return false;
273
	return mwexec("/sbin/gmirror activate " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
274
}
275

    
276
/* Find the size of the given mirror */
277
function gmirror_get_mirror_size($mirror) {
278
	if (!is_valid_mirror($mirror))
279
		return false;
280
	$mirrorsize = "";
281
	exec("/sbin/gmirror list " . escapeshellarg($mirror) . " | /usr/bin/grep 'Mediasize:' | /usr/bin/head -n 1 | /usr/bin/awk '{print $2;}'", $mirrorsize);
282
	return $mirrorsize[0];
283
}
284

    
285
/* Return a list of all potential consumers on a disk with sizes. The geom part
286
	list output is a little odd, we can't get the output for just the disk, if the disk contains
287
	slices those get output also. */
288
function gmirror_get_all_unused_consumer_sizes_on_disk($disk) {
289
	if (!is_valid_disk($disk) || !is_consumer_unused($disk))
290
		return array();
291
	$output = "";
292
	exec("/sbin/geom part list " . escapeshellarg($disk) . " | /usr/bin/egrep '(Name:|Mediasize:)' | /usr/bin/cut -c4- | /usr/bin/sed -l -e 'N;s/\\nMediasize://;P;D;' | /usr/bin/cut -c7-", $output);
293
	$disk_contents = array();
294
	foreach ($output as $line) {
295
		list($name, $size, $humansize) = explode(" ", $line, 3);
296
		$consumer = array();
297
		$consumer['name'] = $name;
298
		$consumer['size'] = $size;
299
		$consumer['humansize'] = $humansize;
300
		$disk_contents[] = $consumer;
301
	}
302
	return $disk_contents;
303
}
304

    
305
/* Get only the size for one specific potential consumer. */
306
function gmirror_get_unused_consumer_size($consumer) {
307
	$consumersizes = gmirror_get_all_unused_consumer_sizes_on_disk($consumer);
308
	foreach ($consumersizes as $csize) {
309
		if ($csize['name'] == $consumer)
310
			return $csize['size'];
311
	}
312
	return -1;
313
}
314
?>
(23-23/68)