Project

General

Profile

Download (12.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
require("guiconfig.inc");
58

    
59
$pgtitle = array(gettext("Diagnostics"), gettext("S.M.A.R.T. Monitor Tools"));
60
$smartctl = "/usr/local/sbin/smartctl";
61
$smartd = "/usr/local/sbin/smartd";
62
$start_script = "/usr/local/etc/rc.d/smartd.sh";
63

    
64
$valid_test_types = array("offline", "short", "long", "conveyance");
65
$valid_info_types = array("i", "H", "c", "A", "a");
66
$valid_log_types = array("error", "selftest");
67

    
68
$closehead = false;
69
include("head.inc");
70

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

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

    
98
function smartmonctl($action) {
99
	global $start_script;
100
	shell_exec($start_script . escapeshellarg($action));
101
}
102

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

    
108
if (!file_exists('/dev/' . $targetdev)) {
109
	echo "Device does not exist, bailing.";
110
	return;
111
}
112

    
113
require_once('classes/Form.class.php');
114

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

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

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

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

    
148
<?php
149
		break;
150
	}
151

    
152
	// Info on devices
153
	case 'info':
154
	{
155
		$type = $_POST['type'];
156

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

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

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

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

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

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

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

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

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

    
234
			// Don't know what all this means, but it adds the config changed header when config is saved
235
			$retval = 0;
236
			config_lock();
237
			if (stristr($retval, "error") != true) {
238
				$savemsg = get_std_save_message($retval);
239
				$style = 'success';
240
				}
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
	// Get users email from the xml file
260
	$pconfig['smartmonemail'] = $config['system']['smartmonemail'];
261

    
262
	$form = new Form();
263

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

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

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

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

    
282
	print($form);
283

    
284
	break;
285
	}
286

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

    
292
		$form = new Form(false);
293

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
496
		$form = new Form(false);
497

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

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

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

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

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

    
522
		break;
523
	}
524
}
525

    
526
include("foot.inc");
(35-35/234)