Project

General

Profile

Download (12.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	diag_smart.php
4
*/
5
/* ====================================================================
6
 *  Copyright (c)  2004-2015  Electric Sheep Fencing, LLC. All rights reserved.
7
 *	Copyright (c)  2006 Eric Friesen
8
 *
9
 *  Redistribution and use in source and binary forms, with or without modification,
10
 *  are permitted provided that the following conditions are met:
11
 *
12
 *  1. Redistributions of source code must retain the above copyright notice,
13
 *      this list of conditions and the following disclaimer.
14
 *
15
 *  2. Redistributions in binary form must reproduce the above copyright
16
 *      notice, this list of conditions and the following disclaimer in
17
 *      the documentation and/or other materials provided with the
18
 *      distribution.
19
 *
20
 *  3. All advertising materials mentioning features or use of this software
21
 *      must display the following acknowledgment:
22
 *      "This product includes software developed by the pfSense Project
23
 *       for use in the pfSense software distribution. (http://www.pfsense.org/).
24
 *
25
 *  4. The names "pfSense" and "pfSense Project" must not be used to
26
 *       endorse or promote products derived from this software without
27
 *       prior written permission. For written permission, please contact
28
 *       coreteam@pfsense.org.
29
 *
30
 *  5. Products derived from this software may not be called "pfSense"
31
 *      nor may "pfSense" appear in their names without prior written
32
 *      permission of the Electric Sheep Fencing, LLC.
33
 *
34
 *  6. Redistributions of any form whatsoever must retain the following
35
 *      acknowledgment:
36
 *
37
 *  "This product includes software developed by the pfSense Project
38
 *  for use in the pfSense software distribution (http://www.pfsense.org/).
39
 *
40
 *  THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
41
 *  EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
44
 *  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 *  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 *  OF THE POSSIBILITY OF SUCH DAMAGE.
52
 *
53
 *  ====================================================================
54
 *
55
 */
56

    
57
##|+PRIV
58
##|*IDENT=page-diagnostics-smart
59
##|*NAME=Diagnostics: S.M.A.R.T. Monitor Tools
60
##|*DESCR=Allow access to the 'Diagnostics: S.M.A.R.T. Monitor Tools' page.
61
##|*MATCH=diag_smart.php*
62
##|-PRIV
63

    
64
require("guiconfig.inc");
65

    
66
$pgtitle = array(gettext("Diagnostics"), gettext("S.M.A.R.T. Monitor Tools"));
67
$smartctl = "/usr/local/sbin/smartctl";
68
$smartd = "/usr/local/sbin/smartd";
69
$start_script = "/usr/local/etc/rc.d/smartd.sh";
70

    
71
$valid_test_types = array("offline", "short", "long", "conveyance");
72
$valid_info_types = array("i", "H", "c", "A", "a");
73
$valid_log_types = array("error", "selftest");
74

    
75
include("head.inc");
76

    
77
// Highlights the words "PASSED", "FAILED", and "WARNING".
78
function add_colors($string) {
79
	// To add words keep arrays matched by numbers
80
	$patterns[0] = '/PASSED/';
81
	$patterns[1] = '/FAILED/';
82
	$patterns[2] = '/Warning/';
83
	$replacements[0] = '<span class="text-success">' . gettext("PASSED") . '</span>';
84
	$replacements[1] = '<span class="text-alert">' . gettext("FAILED") . '</span>';
85
	$replacements[2] = '<span class="text-warning">' . gettext("Warning") . '</span>';
86
	ksort($patterns);
87
	ksort($replacements);
88
	return preg_replace($patterns, $replacements, $string);
89
}
90

    
91
// Edits smartd.conf file, adds or removes email for failed disk reporting
92
function update_email($email) {
93
	// Did they pass an email?
94
	if (!empty($email)) {
95
		// Put it in the smartd.conf file
96
		shell_exec("/usr/bin/sed -i old 's/^DEVICESCAN.*/DEVICESCAN -H -m " . escapeshellarg($email) . "/' /usr/local/etc/smartd.conf");
97
	} else {
98
		// Remove email flags in smartd.conf
99
		shell_exec("/usr/bin/sed -i old 's/^DEVICESCAN.*/DEVICESCAN/' /usr/local/etc/smartd.conf");
100
	}
101
}
102

    
103
function smartmonctl($action) {
104
	global $start_script;
105
	shell_exec($start_script . escapeshellarg($action));
106
}
107

    
108
// What page, aka. action is being wanted
109
// If they "get" a page but don't pass all arguments, smartctl will throw an error
110
$action = (isset($_POST['action']) ? $_POST['action'] : $_GET['action']);
111
$targetdev = basename($_POST['device']);
112

    
113
if (!file_exists('/dev/' . $targetdev)) {
114
	echo "Device does not exist, bailing.";
115
	return;
116
}
117

    
118
$tab_array = array();
119
$tab_array[0] = array(gettext("Information/Tests"), ($action != 'config'), $_SERVER['PHP_SELF'] . "?action=default");
120
$tab_array[1] = array(gettext("Config"), ($action == 'config'), $_SERVER['PHP_SELF'] . "?action=config");
121
display_top_tabs($tab_array);
122

    
123
switch ($action) {
124
	// Testing devices
125
	case 'test':
126
	{
127
		$test = $_POST['testType'];
128
		if (!in_array($test, $valid_test_types)) {
129
			echo "Invalid test type, bailing.";
130
			return;
131
		}
132

    
133
		$output = add_colors(shell_exec($smartctl . " -t " . escapeshellarg($test) . " /dev/" . escapeshellarg($targetdev)));
134
?>
135
		<div class="panel  panel-default">
136
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Test results')?></h2></div>
137
			<div class="panel-body">
138
				<pre><?=$output?></pre>
139
			</div>
140
		</div>
141

    
142
		<form action="diag_smart.php" method="post" name="abort">
143
			<input type="hidden" name="device" value="<?=$targetdev?>" />
144
			<input type="hidden" name="action" value="abort" />
145
			<nav class="action-buttons">
146
				<input type="submit" name="submit"	class="btn btn-danger" value="<?=gettext("Abort")?>" />
147
				<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-default"><?=gettext("Back")?></a>
148
			</nav>
149
		</form>
150

    
151
<?php
152
		break;
153
	}
154

    
155
	// Info on devices
156
	case 'info':
157
	{
158
		$type = $_POST['type'];
159

    
160
		if (!in_array($type, $valid_info_types)) {
161
			print_info_box(gettext("Invalid info type, bailing."), 'danger');
162
			return;
163
		}
164

    
165
		$output = add_colors(shell_exec($smartctl . " -" . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
166
?>
167
		<div class="panel  panel-default">
168
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Information')?></h2></div>
169
			<div class="panel-body">
170
				<pre><?=$output?></pre>
171
			</div>
172
		</div>
173

    
174
		<nav class="action-buttons">
175
			<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-default"><?=gettext("Back")?></a>
176
		</nav>
177
<?php
178
		break;
179
	}
180

    
181
	// View logs
182
	case 'logs':
183
	{
184
		$type = $_POST['type'];
185
		if (!in_array($type, $valid_log_types)) {
186
			print_info_box(gettext("Invalid log type, bailing."), 'danger');
187
			return;
188
		}
189

    
190
		$output = add_colors(shell_exec($smartctl . " -l " . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
191
?>
192
		<div class="panel  panel-default">
193
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Logs')?></h2></div>
194
			<div class="panel-body">
195
				<pre><?=$output?></pre>
196
			</div>
197
		</div>
198

    
199
		<nav class="action-buttons">
200
			<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-default"><?=gettext("Back")?></a>
201
		</nav>
202
<?php
203
		break;
204
	}
205

    
206
	// Abort tests
207
	case 'abort':
208
	{
209
		$output = shell_exec($smartctl . " -X /dev/" . escapeshellarg($targetdev));
210
?>
211
		<div class="panel  panel-default">
212
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Abort')?></h2></div>
213
			<div class="panel-body">
214
				<pre><?=$output?></pre>
215
			</div>
216
		</div>
217
<?php
218
		break;
219
	}
220

    
221
	// Config changes, users email in xml config and write changes to smartd.conf
222
	case 'config':
223
	{
224
		if (isset($_POST['test'])) {
225

    
226
// FIXME				shell_exec($smartd . " -M test -m " . $config['system']['smartmonemail']);
227
			$savemsg = sprintf(gettext("Email sent to %s"), $config['system']['smartmonemail']);
228
			smartmonctl("stop");
229
			smartmonctl("start");
230
			$style = 'warning';
231
		} else if (isset($_POST['save'])) {
232
			$config['system']['smartmonemail'] = $_POST['smartmonemail'];
233
			write_config();
234

    
235
			// Don't know what all this means, but it adds the config changed header when config is saved
236
			$retval = 0;
237
			config_lock();
238
			if (stristr($retval, "error") != true) {
239
				$savemsg = get_std_save_message($retval);
240
				$style = 'success';
241
			} else {
242
				$savemsg = $retval;
243
				$style='danger';
244
			}
245

    
246
			config_unlock();
247

    
248
			// Write the changes to the smartd.conf file
249
			update_email($_POST['smartmonemail']);
250

    
251
			// Send sig HUP to smartd, rereads the config file
252
			shell_exec("/usr/bin/killall -HUP smartd");
253
		}
254

    
255
	// Was the config changed? if so, print the message
256
	if ($savemsg) {
257
		print_info_box($savemsg, $style);
258
	}
259

    
260
	// Get users email from the xml file
261
	$pconfig['smartmonemail'] = $config['system']['smartmonemail'];
262

    
263
	$form = new Form();
264

    
265
	$section = new Form_Section('Configuration');
266

    
267
	$section->addInput(new Form_Input(
268
		'smartmonemail',
269
		'Email Address',
270
		'text',
271
		$pconfig['smartmonemail']
272
	 ));
273

    
274
	$form->add($section);
275

    
276
	if (!empty($pconfig['smartmonemail'])) {
277
		$form->addGlobal(new Form_Button(
278
			'test',
279
			'Send test email'
280
		))->removeClass('btn-primary')->addClass('btn-default');
281
	}
282

    
283
	print($form);
284

    
285
	break;
286
	}
287

    
288
	// Default page, prints the forms to view info, test, etc...
289
	default: {
290
// Information
291
		$devs = get_smart_drive_list();
292

    
293
		$form = new Form(false);
294

    
295
		$btnview = new Form_Button(
296
			'submit',
297
			'View'
298
		);
299

    
300
		$section = new Form_Section('Information');
301

    
302
		$section->addInput(new Form_Input(
303
			'action',
304
			null,
305
			'hidden',
306
			'info'
307
		));
308

    
309
		$group = new Form_Group('Info type');
310

    
311
		$group->add(new Form_Checkbox(
312
			'type',
313
			null,
314
			'Info',
315
			false,
316
			'i'
317
		))->displayAsRadio();
318

    
319
		$group->add(new Form_Checkbox(
320
			'type',
321
			null,
322
			'Health',
323
			true,
324
			'H'
325
		))->displayAsRadio();
326

    
327
		$group->add(new Form_Checkbox(
328
			'type',
329
			null,
330
			'SMART Capabilities',
331
			false,
332
			'c'
333
		))->displayAsRadio();
334

    
335
		$group->add(new Form_Checkbox(
336
			'type',
337
			null,
338
			'Attributes',
339
			false,
340
			'A'
341
		))->displayAsRadio();
342

    
343
		$group->add(new Form_Checkbox(
344
			'type',
345
			null,
346
			'All',
347
			false,
348
			'a'
349
		))->displayAsRadio();
350

    
351
		$section->add($group);
352

    
353
		$section->addInput(new Form_Select(
354
			'device',
355
			'Device: /dev/',
356
			false,
357
			array_combine($devs, $devs)
358
		));
359

    
360
		$section->addInput(new Form_StaticText(
361
			'',
362
			$btnview
363
		));
364

    
365
		$form->add($section);
366
		print($form);
367

    
368
// Tests
369
		$form = new Form(false);
370

    
371
		$btntest = new Form_Button(
372
			'submit',
373
			'Test'
374
		);
375

    
376
		$section = new Form_Section('Perform self-tests');
377

    
378
		$section->addInput(new Form_Input(
379
			'action',
380
			null,
381
			'hidden',
382
			'test'
383
		));
384

    
385
		$group = new Form_Group('Test type');
386

    
387
		$group->add(new Form_Checkbox(
388
			'testType',
389
			null,
390
			'Offline',
391
			false,
392
			'offline'
393
		))->displayAsRadio();
394

    
395
		$group->add(new Form_Checkbox(
396
			'testType',
397
			null,
398
			'Short',
399
			true,
400
			'short'
401
		))->displayAsRadio();
402

    
403
		$group->add(new Form_Checkbox(
404
			'testType',
405
			null,
406
			'Long',
407
			false,
408
			'long'
409
		))->displayAsRadio();
410

    
411
		$group->add(new Form_Checkbox(
412
			'testType',
413
			null,
414
			'Conveyance',
415
			false,
416
			'conveyance'
417
		))->displayAsRadio();
418

    
419
		$group->setHelp('Select "Conveyance" for ATA disks only');
420
		$section->add($group);
421

    
422
		$section->addInput(new Form_Select(
423
			'device',
424
			'Device: /dev/',
425
			false,
426
			array_combine($devs, $devs)
427
		));
428

    
429
		$section->addInput(new Form_StaticText(
430
			'',
431
			$btntest
432
		));
433

    
434
		$form->add($section);
435
		print($form);
436

    
437
// Logs
438
		$form = new Form(false);
439

    
440
		$btnview =  new Form_Button(
441
			'submit',
442
			'View'
443
		);
444

    
445
		$section = new Form_Section('View logs');
446

    
447
		$section->addInput(new Form_Input(
448
			'action',
449
			null,
450
			'hidden',
451
			'logs'
452
		));
453

    
454
		$group = new Form_Group('Log type');
455

    
456
		$group->add(new Form_Checkbox(
457
			'type',
458
			null,
459
			'Error',
460
			true,
461
			'error'
462
		))->displayAsRadio();
463

    
464
		$group->add(new Form_Checkbox(
465
			'test',
466
			null,
467
			'Self-test',
468
			false,
469
			'selftest'
470
		))->displayAsRadio();
471

    
472
		$section->add($group);
473

    
474
		$section->addInput(new Form_Select(
475
			'device',
476
			'Device: /dev/',
477
			false,
478
			array_combine($devs, $devs)
479
		));
480

    
481
		$section->addInput(new Form_StaticText(
482
			'',
483
			$btnview
484
		));
485

    
486
		$form->add($section);
487
		print($form);
488

    
489
// Abort
490
		$btnabort = new Form_Button(
491
			'submit',
492
			'Abort'
493
		);
494

    
495
		$btnabort->removeClass('btn-primary')->addClass('btn-danger');
496

    
497
		$form = new Form(false);
498

    
499
		$section = new Form_Section('Abort');
500

    
501
		$section->addInput(new Form_Input(
502
			'action',
503
			null,
504
			'hidden',
505
			'abort'
506
		));
507

    
508
		$section->addInput(new Form_Select(
509
			'device',
510
			'Device: /dev/',
511
			false,
512
			array_combine($devs, $devs)
513
		));
514

    
515
		$section->addInput(new Form_StaticText(
516
			'',
517
			$btnabort
518
		));
519

    
520
		$form->add($section);
521
		print($form);
522

    
523
		break;
524
	}
525
}
526

    
527
include("foot.inc");
(25-25/229)