Project

General

Profile

Download (13.4 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. Status
60
##|*DESCR=Allow access to the 'Diagnostics: S.M.A.R.T. Status' page.
61
##|*MATCH=diag_smart.php*
62
##|-PRIV
63

    
64
require("guiconfig.inc");
65

    
66
// What page, aka. action is being wanted
67
// If they "get" a page but don't pass all arguments, smartctl will throw an error
68
$action = (isset($_POST['action']) ? $_POST['action'] : $_GET['action']);
69

    
70
$pgtitle = array(gettext("Diagnostics"), gettext("S.M.A.R.T. Status"));
71

    
72
if ($action != 'config') {
73
	$pgtitle[] = htmlspecialchars(gettext('Information & Tests'));
74
} else {
75
	$pgtitle[] = gettext('Config');
76
}
77
$smartctl = "/usr/local/sbin/smartctl";
78
$smartd = "/usr/local/sbin/smartd";
79
$start_script = "/usr/local/etc/rc.d/smartd.sh";
80

    
81
$valid_test_types = array("offline", "short", "long", "conveyance");
82
$valid_info_types = array("i", "H", "c", "A", "a");
83
$valid_log_types = array("error", "selftest");
84

    
85
include("head.inc");
86

    
87
// Highlights the words "PASSED", "FAILED", and "WARNING".
88
function add_colors($string) {
89
	// To add words keep arrays matched by numbers
90
	$patterns[0] = '/PASSED/';
91
	$patterns[1] = '/FAILED/';
92
	$patterns[2] = '/Warning/';
93
	$replacements[0] = '<span class="text-success">' . gettext("PASSED") . '</span>';
94
	$replacements[1] = '<span class="text-alert">' . gettext("FAILED") . '</span>';
95
	$replacements[2] = '<span class="text-warning">' . gettext("Warning") . '</span>';
96
	ksort($patterns);
97
	ksort($replacements);
98
	return preg_replace($patterns, $replacements, $string);
99
}
100

    
101
// Edits smartd.conf file, adds or removes email for failed disk reporting
102
function update_email($email) {
103
	// Did they pass an email?
104
	if (!empty($email)) {
105
		// Put it in the smartd.conf file
106
		shell_exec("/usr/bin/sed -i old 's/^DEVICESCAN.*/DEVICESCAN -H -m " . escapeshellarg($email) . "/' /usr/local/etc/smartd.conf");
107
	} else {
108
		// Remove email flags in smartd.conf
109
		shell_exec("/usr/bin/sed -i old 's/^DEVICESCAN.*/DEVICESCAN/' /usr/local/etc/smartd.conf");
110
	}
111
}
112

    
113
function smartmonctl($action) {
114
	global $start_script;
115
	shell_exec($start_script . escapeshellarg($action));
116
}
117
$targetdev = basename($_POST['device']);
118

    
119
if (!file_exists('/dev/' . $targetdev)) {
120
	echo gettext("Device does not exist, bailing.");
121
	return;
122
}
123

    
124
$tab_array = array();
125
$tab_array[0] = array(htmlspecialchars(gettext("Information & Tests")), ($action != 'config'), $_SERVER['PHP_SELF'] . "?action=default");
126
$tab_array[1] = array(gettext("Config"), ($action == 'config'), $_SERVER['PHP_SELF'] . "?action=config");
127
display_top_tabs($tab_array);
128

    
129
switch ($action) {
130
	// Testing devices
131
	case 'test':
132
	{
133
		$test = $_POST['testType'];
134
		if (!in_array($test, $valid_test_types)) {
135
			echo gettext("Invalid test type, bailing.");
136
			return;
137
		}
138

    
139
		$output = add_colors(shell_exec($smartctl . " -t " . escapeshellarg($test) . " /dev/" . escapeshellarg($targetdev)));
140
?>
141
		<div class="panel  panel-default">
142
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Test Results')?></h2></div>
143
			<div class="panel-body">
144
				<pre><?=$output?></pre>
145
			</div>
146
		</div>
147

    
148
		<form action="diag_smart.php" method="post" name="abort">
149
			<input type="hidden" name="device" value="<?=$targetdev?>" />
150
			<input type="hidden" name="action" value="abort" />
151
			<nav class="action-buttons">
152
				<button type="submit" name="submit" class="btn btn-danger" value="<?=gettext("Abort")?>">
153
					<i class="fa fa-times icon-embed-btn"></i>
154
					<?=gettext("Abort Test")?>
155
				</button>
156
				<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-info">
157
					<i class="fa fa-undo icon-embed-btn"></i>
158
					<?=gettext("Back")?>
159
				</a>
160
			</nav>
161
		</form>
162

    
163
<?php
164
		break;
165
	}
166

    
167
	// Info on devices
168
	case 'info':
169
	{
170
		$type = $_POST['type'];
171

    
172
		if (!in_array($type, $valid_info_types)) {
173
			print_info_box(gettext("Invalid info type, bailing."), 'danger');
174
			return;
175
		}
176

    
177
		$output = add_colors(shell_exec($smartctl . " -" . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
178
?>
179
		<div class="panel  panel-default">
180
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Information')?></h2></div>
181
			<div class="panel-body">
182
				<pre><?=$output?></pre>
183
			</div>
184
		</div>
185

    
186
		<nav class="action-buttons">
187
			<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-info">
188
				<i class="fa fa-undo icon-embed-btn"></i>
189
				<?=gettext("Back")?>
190
			</a>
191
		</nav>
192
<?php
193
		break;
194
	}
195

    
196
	// View logs
197
	case 'logs':
198
	{
199
		$type = $_POST['type'];
200
		if (!in_array($type, $valid_log_types)) {
201
			print_info_box(gettext("Invalid log type, bailing."), 'danger');
202
			return;
203
		}
204

    
205
		$output = add_colors(shell_exec($smartctl . " -l " . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
206
?>
207
		<div class="panel  panel-default">
208
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Logs')?></h2></div>
209
			<div class="panel-body">
210
				<pre><?=$output?></pre>
211
			</div>
212
		</div>
213

    
214
		<nav class="action-buttons">
215
			<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-info">
216
				<i class="fa fa-undo icon-embed-btn"></i>
217
				<?=gettext("Back")?>
218
			</a>
219
		</nav>
220
<?php
221
		break;
222
	}
223

    
224
	// Abort tests
225
	case 'abort':
226
	{
227
		$output = shell_exec($smartctl . " -X /dev/" . escapeshellarg($targetdev));
228
?>
229
		<div class="panel  panel-default">
230
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Abort')?></h2></div>
231
			<div class="panel-body">
232
				<pre><?=$output?></pre>
233
			</div>
234
		</div>
235
<?php
236
		break;
237
	}
238

    
239
	// Config changes, users email in xml config and write changes to smartd.conf
240
	case 'config':
241
	{
242
		if (isset($_POST['test'])) {
243

    
244
// FIXME				shell_exec($smartd . " -M test -m " . $config['system']['smartmonemail']);
245
			$savemsg = sprintf(gettext("Email sent to %s"), $config['system']['smartmonemail']);
246
			smartmonctl("stop");
247
			smartmonctl("start");
248
			$style = 'warning';
249
		} else if (isset($_POST['save'])) {
250
			$config['system']['smartmonemail'] = $_POST['smartmonemail'];
251
			write_config();
252

    
253
			// Don't know what all this means, but it adds the config changed header when config is saved
254
			$retval = 0;
255
			config_lock();
256
			if (stristr($retval, "error") != true) {
257
				$savemsg = get_std_save_message($retval);
258
				$style = 'success';
259
			} else {
260
				$savemsg = $retval;
261
				$style='danger';
262
			}
263

    
264
			config_unlock();
265

    
266
			// Write the changes to the smartd.conf file
267
			update_email($_POST['smartmonemail']);
268

    
269
			// Send sig HUP to smartd, rereads the config file
270
			shell_exec("/usr/bin/killall -HUP smartd");
271
		}
272

    
273
	// Was the config changed? if so, print the message
274
	if ($savemsg) {
275
		print_info_box($savemsg, $style);
276
	}
277

    
278
	// Get users email from the xml file
279
	$pconfig['smartmonemail'] = $config['system']['smartmonemail'];
280

    
281
	$form = new Form();
282

    
283
	$section = new Form_Section('Configuration');
284

    
285
	$section->addInput(new Form_Input(
286
		'smartmonemail',
287
		'Email Address',
288
		'text',
289
		$pconfig['smartmonemail']
290
	 ));
291

    
292
	$form->add($section);
293

    
294
	if (!empty($pconfig['smartmonemail'])) {
295
		$form->addGlobal(new Form_Button(
296
			'test',
297
			'Send test email',
298
			null,
299
			'fa-send'
300
		))->addClass('btn-info');
301
	}
302

    
303
	print($form);
304

    
305
	break;
306
	}
307

    
308
	// Default page, prints the forms to view info, test, etc...
309
	default: {
310
// Information
311
		$devs = get_smart_drive_list();
312

    
313
		$form = new Form(false);
314

    
315
		$btnview = new Form_Button(
316
			'submit',
317
			'View',
318
			null,
319
			'fa-file-o'
320
		);
321
		$btnview->addClass('btn-primary');
322
		$btnview->setAttribute('id');
323

    
324
		$section = new Form_Section('Information');
325

    
326
		$section->addInput(new Form_Input(
327
			'action',
328
			null,
329
			'hidden',
330
			'info'
331
		))->setAttribute('id');
332

    
333
		$group = new Form_Group('Info type');
334

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

    
343
		$group->add(new Form_Checkbox(
344
			'type',
345
			null,
346
			'Health',
347
			true,
348
			'H'
349
		))->displayAsRadio();
350

    
351
		$group->add(new Form_Checkbox(
352
			'type',
353
			null,
354
			'S.M.A.R.T. Capabilities',
355
			false,
356
			'c'
357
		))->displayAsRadio();
358

    
359
		$group->add(new Form_Checkbox(
360
			'type',
361
			null,
362
			'Attributes',
363
			false,
364
			'A'
365
		))->displayAsRadio();
366

    
367
		$group->add(new Form_Checkbox(
368
			'type',
369
			null,
370
			'All',
371
			false,
372
			'a'
373
		))->displayAsRadio();
374

    
375
		$section->add($group);
376

    
377
		$section->addInput(new Form_Select(
378
			'device',
379
			'Device: /dev/',
380
			false,
381
			array_combine($devs, $devs)
382
		))->setAttribute('id');
383

    
384
		$section->addInput(new Form_StaticText(
385
			'',
386
			$btnview
387
		));
388

    
389
		$form->add($section);
390
		print($form);
391

    
392
// Tests
393
		$form = new Form(false);
394

    
395
		$btntest = new Form_Button(
396
			'submit',
397
			'Test',
398
			null,
399
			'fa-wrench'
400
		);
401
		$btntest->addClass('btn-primary');
402
		$btntest->setAttribute('id');
403

    
404
		$section = new Form_Section('Perform self-tests');
405

    
406
		$section->addInput(new Form_Input(
407
			'action',
408
			null,
409
			'hidden',
410
			'test'
411
		))->setAttribute('id');
412

    
413
		$group = new Form_Group('Test type');
414

    
415
		$group->add(new Form_Checkbox(
416
			'testType',
417
			null,
418
			'Offline',
419
			false,
420
			'offline'
421
		))->displayAsRadio();
422

    
423
		$group->add(new Form_Checkbox(
424
			'testType',
425
			null,
426
			'Short',
427
			true,
428
			'short'
429
		))->displayAsRadio();
430

    
431
		$group->add(new Form_Checkbox(
432
			'testType',
433
			null,
434
			'Long',
435
			false,
436
			'long'
437
		))->displayAsRadio();
438

    
439
		$group->add(new Form_Checkbox(
440
			'testType',
441
			null,
442
			'Conveyance',
443
			false,
444
			'conveyance'
445
		))->displayAsRadio();
446

    
447
		$group->setHelp('Select "Conveyance" for ATA disks only');
448
		$section->add($group);
449

    
450
		$section->addInput(new Form_Select(
451
			'device',
452
			'Device: /dev/',
453
			false,
454
			array_combine($devs, $devs)
455
		))->setAttribute('id');
456

    
457
		$section->addInput(new Form_StaticText(
458
			'',
459
			$btntest
460
		));
461

    
462
		$form->add($section);
463
		print($form);
464

    
465
// Logs
466
		$form = new Form(false);
467

    
468
		$btnview =  new Form_Button(
469
			'submit',
470
			'View',
471
			null,
472
			'fa-file-o'
473
		);
474
		$btnview->addClass('btn-primary');
475
		$btnview->setAttribute('id');
476

    
477
		$section = new Form_Section('View Logs');
478

    
479
		$section->addInput(new Form_Input(
480
			'action',
481
			null,
482
			'hidden',
483
			'logs'
484
		))->setAttribute('id');
485

    
486
		$group = new Form_Group('Log type');
487

    
488
		$group->add(new Form_Checkbox(
489
			'type',
490
			null,
491
			'Error',
492
			true,
493
			'error'
494
		))->displayAsRadio();
495

    
496
		$group->add(new Form_Checkbox(
497
			'type',
498
			null,
499
			'Self-test',
500
			false,
501
			'selftest'
502
		))->displayAsRadio();
503

    
504
		$section->add($group);
505

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

    
513
		$section->addInput(new Form_StaticText(
514
			'',
515
			$btnview
516
		));
517

    
518
		$form->add($section);
519
		print($form);
520

    
521
// Abort
522
		$btnabort = new Form_Button(
523
			'submit',
524
			'Abort',
525
			null,
526
			'fa-times'
527
		);
528

    
529
		$btnabort->addClass('btn-danger')->setAttribute('id');
530

    
531
		$form = new Form(false);
532

    
533
		$section = new Form_Section('Abort');
534

    
535
		$section->addInput(new Form_Input(
536
			'action',
537
			null,
538
			'hidden',
539
			'abort'
540
		))->setAttribute('id');
541

    
542
		$section->addInput(new Form_Select(
543
			'device',
544
			'Device: /dev/',
545
			false,
546
			array_combine($devs, $devs)
547
		))->setAttribute('id');
548

    
549
		$section->addInput(new Form_StaticText(
550
			'',
551
			$btnabort
552
		));
553

    
554
		$form->add($section);
555
		print($form);
556

    
557
		break;
558
	}
559
}
560

    
561
include("foot.inc");
(27-27/227)