Project

General

Profile

Download (12.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. 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
$closehead = false;
76
include("head.inc");
77

    
78
// Highlights the words "PASSED", "FAILED", and "WARNING".
79
function add_colors($string) {
80
	// To add words keep arrays matched by numbers
81
	$patterns[0] = '/PASSED/';
82
	$patterns[1] = '/FAILED/';
83
	$patterns[2] = '/Warning/';
84
	$replacements[0] = '<b><font color="#00ff00">' . gettext("PASSED") .  '</font></b>';
85
	$replacements[1] = '<b><font color="#ff0000">' . gettext("FAILED") .  '</font></b>';
86
	$replacements[2] = '<font color="#ff0000">'	   . gettext("Warning") . '</font>';
87
	ksort($patterns);
88
	ksort($replacements);
89
	return preg_replace($patterns, $replacements, $string);
90
}
91

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

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

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

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

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

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

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

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

    
152
<?php
153
		break;
154
	}
155

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

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

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

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

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

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

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

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

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

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

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

    
247
			config_unlock();
248

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

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

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

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

    
264
	$form = new Form();
265

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

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

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

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

    
284
	print($form);
285

    
286
	break;
287
	}
288

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

    
294
		$form = new Form(false);
295

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
498
		$form = new Form(false);
499

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

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

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

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

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

    
524
		break;
525
	}
526
}
527

    
528
include("foot.inc");
(25-25/228)