Project

General

Profile

Download (10.8 KB) Statistics
| Branch: | Tag: | Revision:
1 52398a6b jim-p
<?php
2
/*
3 ac24dc24 Renato Botelho
 * gmirror.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6 38809d47 Renato Botelho do Couto
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8 a68f7a3d Luiz Otavio O Souza
 * Copyright (c) 2014-2024 Rubicon Communications, LLC (Netgate)
9 ac24dc24 Renato Botelho
 * All rights reserved.
10
 *
11 b12ea3fb Renato Botelho
 * Licensed under the Apache License, Version 2.0 (the "License");
12
 * you may not use this file except in compliance with the License.
13
 * You may obtain a copy of the License at
14 ac24dc24 Renato Botelho
 *
15 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
16 ac24dc24 Renato Botelho
 *
17 b12ea3fb Renato Botelho
 * Unless required by applicable law or agreed to in writing, software
18
 * distributed under the License is distributed on an "AS IS" BASIS,
19
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 * See the License for the specific language governing permissions and
21
 * limitations under the License.
22 ac24dc24 Renato Botelho
 */
23 52398a6b jim-p
24
global $balance_methods;
25
$balance_methods = array("load", "prefer", "round-robin", "split");
26
27
/* Create a status array for each mirror and its disk components. */
28
function gmirror_get_status() {
29
	$status = "";
30
	exec("/sbin/gmirror status -s", $status);
31
	$mirrors = array();
32
33
	/* Empty output = no mirrors found */
34
	if (count($status) > 0) {
35
		/* Loop through gmirror status output. */
36
		foreach ($status as $line) {
37
			/* Split the line by whitespace */
38
			$all = preg_split("/[\s\t]+/", trim($line), 3);
39
			if (count($all) == 3) {
40
				/* If there are three items on a line, it is mirror name, status, and component */
41
				$currentmirror = basename($all[0]);
42
				$mirrors[$currentmirror]['name'] = basename($all[0]);
43
				$mirrors[$currentmirror]['status'] = $all[1];
44 9ba87997 Phil Davis
				if (!is_array($mirrors[$currentmirror]['components'])) {
45 52398a6b jim-p
					$mirrors[$currentmirror]['components'] = array();
46 9ba87997 Phil Davis
				}
47 52398a6b jim-p
				$mirrors[$currentmirror]['components'][] = $all[2];
48
			}
49
		}
50
	}
51 1180e4f0 Sjon Hortensius
	/* Return an hash of mirrors and components */
52 52398a6b jim-p
	return $mirrors;
53
}
54
55
/* Get only status word for a single mirror. */
56
function gmirror_get_status_single($mirror) {
57
	$status = "";
58
	$mirror_status = gmirror_get_status();
59
	return $mirror_status[$mirror]['status'];
60
}
61
62
/* Generate an HTML formatted status for mirrors and disks in a small format for the widget */
63
function gmirror_html_status() {
64
	$mirrors = gmirror_get_status();
65
	$output = "";
66 7d5b007c Sjon Hortensius
	if (count($mirrors) < 1) {
67 02342d8c k-paulius
		print_info_box(gettext("No mirrors found."), 'warning', false);
68 7d5b007c Sjon Hortensius
		return;
69 52398a6b jim-p
	}
70 7d5b007c Sjon Hortensius
71
?>
72 89f64f0f Sander van Leeuwen
<table class="table table-striped table-hover">
73 7d5b007c Sjon Hortensius
	<thead>
74
		<tr>
75 221c0775 Phil Davis
			<th><?=gettext("Name")?></td>
76
			<th><?=gettext("Status")?></td>
77
			<th><?=gettext("Component")?></td>
78 7d5b007c Sjon Hortensius
		</tr>
79
	</thead>
80
	<tbody>
81
<?php foreach ($mirrors as $mirror => $name): ?>
82
		<tr>
83
			<td rowspan="<?=count($name["components"])?>"><?=$name['name']?></td>
84
			<td rowspan="<?=count($name["components"])?>"><?=$name['status']?></td>
85
			<td><?=$name['components'][0]?></td>
86
		</tr>
87
<?php if (count($name["components"]) > 1): ?>
88
		<?php foreach (array_slice($name["components"], 1) as $component): ?>
89
			<tr>
90
				<td><?=$component?></td>
91
			</tr>
92
		<?php endforeach; ?>
93
	<?php endif; ?>
94 221c0775 Phil Davis
<?php endforeach; ?>
95
	</tbody>
96
</table>
97
<?php
98 52398a6b jim-p
}
99
100
/* List all disks in the system (potential gmirror targets) */
101
function gmirror_get_disks() {
102
	$disklist = "";
103
	/* Get a list of disks in a scriptable way, exclude optical drives */
104
	exec("/sbin/geom disk status -s | /usr/bin/grep -v '[[:blank:]]*cd[[:digit:]]*' | /usr/bin/awk '{print $1;}'", $disklist);
105
	return $disklist;
106
}
107
108
/* List all potential gmirror consumers */
109
function gmirror_get_unused_consumers() {
110
	$consumerlist = "";
111 0373c361 jim-p
	$disklist = gmirror_get_disks();
112 52398a6b jim-p
	/* Get a list of consumers, exclude existing mirrors and diskid entries */
113
	exec("/sbin/geom part status -s | /usr/bin/egrep -v '(mirror|diskid)' | /usr/bin/awk '{print $1, $3;}'", $consumerlist);
114
	$all_consumers = array();
115
	foreach ($consumerlist as $cl) {
116
		$parts = explode(" ", $cl);
117 9ba87997 Phil Davis
		foreach ($parts as $part) {
118 52398a6b jim-p
			$all_consumers[] = $part;
119 9ba87997 Phil Davis
		}
120 52398a6b jim-p
	}
121 0373c361 jim-p
	foreach ($disklist as $d) {
122
		if (!is_consumer_used($d) && !in_array($d, $all_consumers)) {
123
			$all_consumers[] = $d;
124
		}
125
	}
126 52398a6b jim-p
	return $all_consumers;
127
}
128
129
/* List all existing geom mirrors */
130
function gmirror_get_mirrors() {
131
	$mirrorlist = "";
132
	exec("/sbin/gmirror list | /usr/bin/grep '^Geom name:' | /usr/bin/awk '{print $3;}'", $mirrorlist);
133
	return $mirrorlist;
134
}
135
136
137
/* List all consumers for a given mirror */
138
function gmirror_get_consumers_in_mirror($mirror) {
139 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror)) {
140 52398a6b jim-p
		return array();
141 9ba87997 Phil Davis
	}
142 52398a6b jim-p
143
	$consumers = array();
144
	exec("/sbin/gmirror status -s " . escapeshellarg($mirror) . " | /usr/bin/awk '{print $3;}'", $consumers);
145
	return $consumers;
146
}
147
148
/* Test if a given consumer is a member of an existing mirror */
149
function is_consumer_in_mirror($consumer, $mirror) {
150 9ba87997 Phil Davis
	if (!is_valid_consumer($consumer) || !is_valid_mirror($mirror)) {
151 52398a6b jim-p
		return false;
152 9ba87997 Phil Davis
	}
153 52398a6b jim-p
154
	$mirrorconsumers = gmirror_get_consumers_in_mirror($mirror);
155
	return in_array(basename($consumer), $mirrorconsumers);
156
}
157
158
/* Test if a mirror exists */
159
function is_valid_mirror($mirror) {
160
	$mirrors = gmirror_get_mirrors();
161
	return in_array($mirror, $mirrors);
162
}
163
164
/* Test if a disk is valid/exists */
165
function is_valid_disk($disk) {
166
	$adisks = gmirror_get_disks();
167
	return in_array(basename($disk), $adisks);
168
}
169
170
/* Test if a consumer is valid and in use in a mirror */
171
function is_consumer_used($consumer) {
172
	$found = false;
173
	$mirrors = gmirror_get_mirrors();
174
	foreach ($mirrors as $mirror) {
175
		$consumers = gmirror_get_consumers_in_mirror($mirror);
176 9ba87997 Phil Davis
		if (in_array($consumer, $consumers)) {
177 52398a6b jim-p
			return true;
178 9ba87997 Phil Davis
		}
179 52398a6b jim-p
	}
180
	return false;
181
}
182
183
/* Test if a consumer is valid and not in use */
184
function is_consumer_unused($consumer) {
185
	$consumers = gmirror_get_unused_consumers();
186
	return in_array($consumer, $consumers);
187
}
188
189
/* Test if a consumer is valid (either a disk or partition) */
190
function is_valid_consumer($consumer) {
191
	return (is_consumer_unused($consumer) || is_consumer_used($consumer));
192
}
193
194
/* Remove all disconnected drives from a mirror */
195
function gmirror_forget_disconnected($mirror) {
196 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror)) {
197 52398a6b jim-p
		return false;
198 9ba87997 Phil Davis
	}
199 52398a6b jim-p
	return mwexec("/sbin/gmirror forget " . escapeshellarg($mirror));
200
}
201
202
/* Insert another consumer into a mirror */
203
function gmirror_insert_consumer($mirror, $consumer) {
204 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer)) {
205 52398a6b jim-p
		return false;
206 9ba87997 Phil Davis
	}
207 52398a6b jim-p
	return mwexec("/sbin/gmirror insert " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
208
}
209
210
/* Remove consumer from a mirror and clear its metadata */
211
function gmirror_remove_consumer($mirror, $consumer) {
212 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer)) {
213 52398a6b jim-p
		return false;
214 9ba87997 Phil Davis
	}
215 52398a6b jim-p
	return mwexec("/sbin/gmirror remove " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
216
}
217
218
/* Wipe geom info from drive (if mirror is not running) */
219
function gmirror_clear_consumer($consumer) {
220 9ba87997 Phil Davis
	if (!is_valid_consumer($consumer)) {
221 52398a6b jim-p
		return false;
222 9ba87997 Phil Davis
	}
223 52398a6b jim-p
	return mwexec("/sbin/gmirror clear " . escapeshellarg($consumer));
224
}
225
226
/* Find the balance method used by a given mirror */
227
function gmirror_get_mirror_balance($mirror) {
228 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror)) {
229 52398a6b jim-p
		return false;
230 9ba87997 Phil Davis
	}
231 52398a6b jim-p
	$balancemethod = "";
232
	exec("/sbin/gmirror list " . escapeshellarg($mirror) . " | /usr/bin/grep '^Balance:' | /usr/bin/awk '{print $2;}'", $balancemethod);
233
	return $balancemethod[0];
234
}
235
236
/* Change balance algorithm of the mirror */
237
function gmirror_configure_balance($mirror, $balancemethod) {
238 2fc7b003 jim-p
	global $balance_methods;
239 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror) || !in_array($balancemethod, $balance_methods)) {
240 52398a6b jim-p
		return false;
241 9ba87997 Phil Davis
	}
242 52398a6b jim-p
	return mwexec("/sbin/gmirror configure -b " . escapeshellarg($balancemethod) . " " . escapeshellarg($mirror));
243
}
244
245
/* Force a mirror member to rebuild */
246
function gmirror_force_rebuild($mirror, $consumer) {
247 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer)) {
248 52398a6b jim-p
		return false;
249 9ba87997 Phil Davis
	}
250 52398a6b jim-p
	return mwexec("/sbin/gmirror rebuild " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
251
}
252
253
/* Show all metadata on the physical consumer */
254
function gmirror_get_consumer_metadata($consumer) {
255 9ba87997 Phil Davis
	if (!is_valid_consumer($consumer)) {
256 52398a6b jim-p
		return array();
257 9ba87997 Phil Davis
	}
258 58b07c57 NewEraCracker
	$output = array();
259 52398a6b jim-p
	exec("/sbin/gmirror dump " . escapeshellarg($consumer), $output);
260
	return array_map('trim', $output);
261
}
262
263
/* Test if a consumer has metadata, indicating it is a member of a mirror (active or inactive) */
264
function gmirror_consumer_has_metadata($consumer) {
265
	return (count(gmirror_get_consumer_metadata($consumer)) > 0);
266
}
267
268
/* Find the mirror to which this consumer belongs */
269
function gmirror_get_consumer_metadata_mirror($consumer) {
270 9ba87997 Phil Davis
	if (!is_valid_consumer($consumer)) {
271 52398a6b jim-p
		return array();
272 9ba87997 Phil Davis
	}
273 52398a6b jim-p
	$metadata = gmirror_get_consumer_metadata($consumer);
274
	foreach ($metadata as $line) {
275
		if (substr($line, 0, 5) == "name:") {
276
			list ($key, $value) = explode(":", $line, 2);
277
			return trim($value);
278
		}
279
	}
280
}
281
282
/* Deactivate consumer, removing it from service in the mirror, but leave metadata intact */
283
function gmirror_deactivate_consumer($mirror, $consumer) {
284 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer)) {
285 52398a6b jim-p
		return false;
286 9ba87997 Phil Davis
	}
287 52398a6b jim-p
	return mwexec("/sbin/gmirror deactivate " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
288
}
289
290
/* Reactivate a deactivated consumer */
291
function gmirror_activate_consumer($mirror, $consumer) {
292 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror) || !is_valid_consumer($consumer)) {
293 52398a6b jim-p
		return false;
294 9ba87997 Phil Davis
	}
295 52398a6b jim-p
	return mwexec("/sbin/gmirror activate " . escapeshellarg($mirror) . " " . escapeshellarg($consumer));
296
}
297
298
/* Find the size of the given mirror */
299
function gmirror_get_mirror_size($mirror) {
300 9ba87997 Phil Davis
	if (!is_valid_mirror($mirror)) {
301 52398a6b jim-p
		return false;
302 9ba87997 Phil Davis
	}
303 52398a6b jim-p
	$mirrorsize = "";
304
	exec("/sbin/gmirror list " . escapeshellarg($mirror) . " | /usr/bin/grep 'Mediasize:' | /usr/bin/head -n 1 | /usr/bin/awk '{print $2;}'", $mirrorsize);
305
	return $mirrorsize[0];
306
}
307
308
/* Return a list of all potential consumers on a disk with sizes. The geom part
309
	list output is a little odd, we can't get the output for just the disk, if the disk contains
310
	slices those get output also. */
311
function gmirror_get_all_unused_consumer_sizes_on_disk($disk) {
312 9ba87997 Phil Davis
	if (!is_valid_disk($disk) || !is_consumer_unused($disk)) {
313 52398a6b jim-p
		return array();
314 9ba87997 Phil Davis
	}
315 58b07c57 NewEraCracker
	$output = array();
316 52398a6b jim-p
	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);
317 0373c361 jim-p
	if (empty($output)) {
318
		exec("/sbin/geom disk 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);
319
	}
320 52398a6b jim-p
	$disk_contents = array();
321
	foreach ($output as $line) {
322
		list($name, $size, $humansize) = explode(" ", $line, 3);
323
		$consumer = array();
324
		$consumer['name'] = $name;
325
		$consumer['size'] = $size;
326
		$consumer['humansize'] = $humansize;
327
		$disk_contents[] = $consumer;
328
	}
329
	return $disk_contents;
330
}
331
332
/* Get only the size for one specific potential consumer. */
333
function gmirror_get_unused_consumer_size($consumer) {
334
	$consumersizes = gmirror_get_all_unused_consumer_sizes_on_disk($consumer);
335
	foreach ($consumersizes as $csize) {
336 9ba87997 Phil Davis
		if ($csize['name'] == $consumer) {
337 52398a6b jim-p
			return $csize['size'];
338 9ba87997 Phil Davis
		}
339 52398a6b jim-p
	}
340
	return -1;
341
}
342 8b335b7a Ermal LUÇI
?>