Project

General

Profile

Download (13.6 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
$specplatform = system_identify_specific_platform();
130
if ($specplatform['name'] == "Hyper-V") {
131
	echo gettext("S.M.A.R.T. is not supported in Hyper-V guests.");
132
	include("foot.inc");
133
	exit;
134
}
135

    
136
switch ($action) {
137
	// Testing devices
138
	case 'test':
139
	{
140
		$test = $_POST['testType'];
141
		if (!in_array($test, $valid_test_types)) {
142
			echo gettext("Invalid test type, bailing.");
143
			return;
144
		}
145

    
146
		$output = add_colors(shell_exec($smartctl . " -t " . escapeshellarg($test) . " /dev/" . escapeshellarg($targetdev)));
147
?>
148
		<div class="panel  panel-default">
149
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Test Results')?></h2></div>
150
			<div class="panel-body">
151
				<pre><?=$output?></pre>
152
			</div>
153
		</div>
154

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

    
170
<?php
171
		break;
172
	}
173

    
174
	// Info on devices
175
	case 'info':
176
	{
177
		$type = $_POST['type'];
178

    
179
		if (!in_array($type, $valid_info_types)) {
180
			print_info_box(gettext("Invalid info type, bailing."), 'danger');
181
			return;
182
		}
183

    
184
		$output = add_colors(shell_exec($smartctl . " -" . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
185
?>
186
		<div class="panel  panel-default">
187
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Information')?></h2></div>
188
			<div class="panel-body">
189
				<pre><?=$output?></pre>
190
			</div>
191
		</div>
192

    
193
		<nav class="action-buttons">
194
			<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-info">
195
				<i class="fa fa-undo icon-embed-btn"></i>
196
				<?=gettext("Back")?>
197
			</a>
198
		</nav>
199
<?php
200
		break;
201
	}
202

    
203
	// View logs
204
	case 'logs':
205
	{
206
		$type = $_POST['type'];
207
		if (!in_array($type, $valid_log_types)) {
208
			print_info_box(gettext("Invalid log type, bailing."), 'danger');
209
			return;
210
		}
211

    
212
		$output = add_colors(shell_exec($smartctl . " -l " . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
213
?>
214
		<div class="panel  panel-default">
215
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Logs')?></h2></div>
216
			<div class="panel-body">
217
				<pre><?=$output?></pre>
218
			</div>
219
		</div>
220

    
221
		<nav class="action-buttons">
222
			<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-info">
223
				<i class="fa fa-undo icon-embed-btn"></i>
224
				<?=gettext("Back")?>
225
			</a>
226
		</nav>
227
<?php
228
		break;
229
	}
230

    
231
	// Abort tests
232
	case 'abort':
233
	{
234
		$output = shell_exec($smartctl . " -X /dev/" . escapeshellarg($targetdev));
235
?>
236
		<div class="panel  panel-default">
237
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Abort')?></h2></div>
238
			<div class="panel-body">
239
				<pre><?=$output?></pre>
240
			</div>
241
		</div>
242
<?php
243
		break;
244
	}
245

    
246
	// Config changes, users email in xml config and write changes to smartd.conf
247
	case 'config':
248
	{
249
		if (isset($_POST['test'])) {
250

    
251
// FIXME				shell_exec($smartd . " -M test -m " . $config['system']['smartmonemail']);
252
			$savemsg = sprintf(gettext("Email sent to %s"), $config['system']['smartmonemail']);
253
			smartmonctl("stop");
254
			smartmonctl("start");
255
			$style = 'warning';
256
		} else if (isset($_POST['save'])) {
257
			$config['system']['smartmonemail'] = $_POST['smartmonemail'];
258
			write_config();
259

    
260
			// Don't know what all this means, but it adds the config changed header when config is saved
261
			$retval = 0;
262
			config_lock();
263
			if (stristr($retval, "error") != true) {
264
				$savemsg = get_std_save_message($retval);
265
				$style = 'success';
266
			} else {
267
				$savemsg = $retval;
268
				$style='danger';
269
			}
270

    
271
			config_unlock();
272

    
273
			// Write the changes to the smartd.conf file
274
			update_email($_POST['smartmonemail']);
275

    
276
			// Send sig HUP to smartd, rereads the config file
277
			shell_exec("/usr/bin/killall -HUP smartd");
278
		}
279

    
280
	// Was the config changed? if so, print the message
281
	if ($savemsg) {
282
		print_info_box($savemsg, $style);
283
	}
284

    
285
	// Get users email from the xml file
286
	$pconfig['smartmonemail'] = $config['system']['smartmonemail'];
287

    
288
	$form = new Form();
289

    
290
	$section = new Form_Section('Configuration');
291

    
292
	$section->addInput(new Form_Input(
293
		'smartmonemail',
294
		'Email Address',
295
		'text',
296
		$pconfig['smartmonemail']
297
	 ));
298

    
299
	$form->add($section);
300

    
301
	if (!empty($pconfig['smartmonemail'])) {
302
		$form->addGlobal(new Form_Button(
303
			'test',
304
			'Send test email',
305
			null,
306
			'fa-send'
307
		))->addClass('btn-info');
308
	}
309

    
310
	print($form);
311

    
312
	break;
313
	}
314

    
315
	// Default page, prints the forms to view info, test, etc...
316
	default: {
317
// Information
318
		$devs = get_smart_drive_list();
319

    
320
		$form = new Form(false);
321

    
322
		$btnview = new Form_Button(
323
			'submit',
324
			'View',
325
			null,
326
			'fa-file-text-o'
327
		);
328
		$btnview->addClass('btn-primary');
329
		$btnview->setAttribute('id');
330

    
331
		$section = new Form_Section('Information');
332

    
333
		$section->addInput(new Form_Input(
334
			'action',
335
			null,
336
			'hidden',
337
			'info'
338
		))->setAttribute('id');
339

    
340
		$group = new Form_Group('Info type');
341

    
342
		$group->add(new Form_Checkbox(
343
			'type',
344
			null,
345
			'Info',
346
			false,
347
			'i'
348
		))->displayAsRadio();
349

    
350
		$group->add(new Form_Checkbox(
351
			'type',
352
			null,
353
			'Health',
354
			true,
355
			'H'
356
		))->displayAsRadio();
357

    
358
		$group->add(new Form_Checkbox(
359
			'type',
360
			null,
361
			'S.M.A.R.T. Capabilities',
362
			false,
363
			'c'
364
		))->displayAsRadio();
365

    
366
		$group->add(new Form_Checkbox(
367
			'type',
368
			null,
369
			'Attributes',
370
			false,
371
			'A'
372
		))->displayAsRadio();
373

    
374
		$group->add(new Form_Checkbox(
375
			'type',
376
			null,
377
			'All',
378
			false,
379
			'a'
380
		))->displayAsRadio();
381

    
382
		$section->add($group);
383

    
384
		$section->addInput(new Form_Select(
385
			'device',
386
			'Device: /dev/',
387
			false,
388
			array_combine($devs, $devs)
389
		))->setAttribute('id');
390

    
391
		$section->addInput(new Form_StaticText(
392
			'',
393
			$btnview
394
		));
395

    
396
		$form->add($section);
397
		print($form);
398

    
399
// Tests
400
		$form = new Form(false);
401

    
402
		$btntest = new Form_Button(
403
			'submit',
404
			'Test',
405
			null,
406
			'fa-wrench'
407
		);
408
		$btntest->addClass('btn-primary');
409
		$btntest->setAttribute('id');
410

    
411
		$section = new Form_Section('Perform self-tests');
412

    
413
		$section->addInput(new Form_Input(
414
			'action',
415
			null,
416
			'hidden',
417
			'test'
418
		))->setAttribute('id');
419

    
420
		$group = new Form_Group('Test type');
421

    
422
		$group->add(new Form_Checkbox(
423
			'testType',
424
			null,
425
			'Offline',
426
			false,
427
			'offline'
428
		))->displayAsRadio();
429

    
430
		$group->add(new Form_Checkbox(
431
			'testType',
432
			null,
433
			'Short',
434
			true,
435
			'short'
436
		))->displayAsRadio();
437

    
438
		$group->add(new Form_Checkbox(
439
			'testType',
440
			null,
441
			'Long',
442
			false,
443
			'long'
444
		))->displayAsRadio();
445

    
446
		$group->add(new Form_Checkbox(
447
			'testType',
448
			null,
449
			'Conveyance',
450
			false,
451
			'conveyance'
452
		))->displayAsRadio();
453

    
454
		$group->setHelp('Select "Conveyance" for ATA disks only.');
455
		$section->add($group);
456

    
457
		$section->addInput(new Form_Select(
458
			'device',
459
			'Device: /dev/',
460
			false,
461
			array_combine($devs, $devs)
462
		))->setAttribute('id');
463

    
464
		$section->addInput(new Form_StaticText(
465
			'',
466
			$btntest
467
		));
468

    
469
		$form->add($section);
470
		print($form);
471

    
472
// Logs
473
		$form = new Form(false);
474

    
475
		$btnview =  new Form_Button(
476
			'submit',
477
			'View',
478
			null,
479
			'fa-file-text-o'
480
		);
481
		$btnview->addClass('btn-primary');
482
		$btnview->setAttribute('id');
483

    
484
		$section = new Form_Section('View Logs');
485

    
486
		$section->addInput(new Form_Input(
487
			'action',
488
			null,
489
			'hidden',
490
			'logs'
491
		))->setAttribute('id');
492

    
493
		$group = new Form_Group('Log type');
494

    
495
		$group->add(new Form_Checkbox(
496
			'type',
497
			null,
498
			'Error',
499
			true,
500
			'error'
501
		))->displayAsRadio();
502

    
503
		$group->add(new Form_Checkbox(
504
			'type',
505
			null,
506
			'Self-test',
507
			false,
508
			'selftest'
509
		))->displayAsRadio();
510

    
511
		$section->add($group);
512

    
513
		$section->addInput(new Form_Select(
514
			'device',
515
			'Device: /dev/',
516
			false,
517
			array_combine($devs, $devs)
518
		))->setAttribute('id');
519

    
520
		$section->addInput(new Form_StaticText(
521
			'',
522
			$btnview
523
		));
524

    
525
		$form->add($section);
526
		print($form);
527

    
528
// Abort
529
		$btnabort = new Form_Button(
530
			'submit',
531
			'Abort',
532
			null,
533
			'fa-times'
534
		);
535

    
536
		$btnabort->addClass('btn-danger')->setAttribute('id');
537

    
538
		$form = new Form(false);
539

    
540
		$section = new Form_Section('Abort');
541

    
542
		$section->addInput(new Form_Input(
543
			'action',
544
			null,
545
			'hidden',
546
			'abort'
547
		))->setAttribute('id');
548

    
549
		$section->addInput(new Form_Select(
550
			'device',
551
			'Device: /dev/',
552
			false,
553
			array_combine($devs, $devs)
554
		))->setAttribute('id');
555

    
556
		$section->addInput(new Form_StaticText(
557
			'',
558
			$btnabort
559
		));
560

    
561
		$form->add($section);
562
		print($form);
563

    
564
		break;
565
	}
566
}
567

    
568
include("foot.inc");
(27-27/225)