Project

General

Profile

Download (9.49 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * diag_smart.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2020 Rubicon Communications, LLC (Netgate)
9
 * Copyright (c) 2006 Eric Friesen
10
 * All rights reserved.
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 * http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24

    
25
##|+PRIV
26
##|*IDENT=page-diagnostics-smart
27
##|*NAME=Diagnostics: S.M.A.R.T. Status
28
##|*DESCR=Allow access to the 'Diagnostics: S.M.A.R.T. Status' page.
29
##|*MATCH=diag_smart.php*
30
##|-PRIV
31

    
32
require_once("guiconfig.inc");
33

    
34
// What page, aka. action is being wanted
35
// If they "get" a page but don't pass all arguments, smartctl will throw an error
36
$action = $_POST['action'];
37

    
38
$pgtitle = array(gettext("Diagnostics"), gettext("S.M.A.R.T. Status"));
39
$pglinks = array("", "@self", "@self");
40

    
41
if ($action != 'config') {
42
	$pgtitle[] = htmlspecialchars(gettext('Information & Tests'));
43
} else {
44
	$pgtitle[] = gettext('Config');
45
}
46

    
47
$smartctl = "/usr/local/sbin/smartctl";
48

    
49
$test_types = array(
50
	'offline' => gettext('Offline Test'),
51
	'short' => gettext('Short Test'),
52
	'long' => gettext('Long Test'),
53
	'conveyance' => gettext('Conveyance Test')
54
);
55
$info_types = array(
56
	'x' => gettext('All SMART and Non-SMART Information'),
57
	'a' => gettext('All SMART Information'),
58
	'i' => gettext('Device Information'),
59
	'H' => gettext('Device Health'),
60
	'c' => gettext('SMART Capabilities'),
61
	'A' => gettext('SMART Attributes'),
62
);
63
$log_types = array(
64
	'error' => gettext('Summary Error Log'),
65
	'xerror' => gettext('Extended Error Log'),
66
	'selftest' => gettext('SMART Self-Test Log'),
67
	'xselftest' => gettext('Extended Self-Test Log'),
68
	'selective' => gettext('Selective Self-Test Log'),
69
	'directory' => gettext('Log Directory'),
70
	'scttemp' => gettext('Device Temperature Log (ATA Only)'),
71
	'devstat' => gettext('Device Statistics (ATA Only)'),
72
	'sataphy' => gettext('SATA PHY Events (SATA Only)'),
73
	'sasphy' => gettext('SAS PHY Events (SAS Only)'),
74
	'nvmelog' => gettext('NVMe Log (NVMe Only)'),
75
	'ssd' => gettext('SSD Device Statistics (ATA/SCSI)'),
76
);
77

    
78
include("head.inc");
79

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

    
94
$targetdev = basename($_POST['device']);
95

    
96
if (!file_exists('/dev/' . $targetdev)) {
97
	echo gettext("Device does not exist, bailing.");
98
	return;
99
}
100

    
101
$specplatform = system_identify_specific_platform();
102
if (($specplatform['name'] == "Hyper-V") || ($specplatform['name'] == "uFW")) {
103
	echo sprintf(gettext("S.M.A.R.T. is not supported on this system (%s)."), $specplatform['descr']);
104
	include("foot.inc");
105
	exit;
106
}
107

    
108
switch ($action) {
109
	// Testing devices
110
	case 'test':
111
	{
112
		$test = $_POST['type'];
113
		if (!in_array($test, array_keys($test_types))) {
114
			echo gettext("Invalid test type, bailing.");
115
			return;
116
		}
117

    
118
		$output = add_colors(shell_exec($smartctl . " -t " . escapeshellarg($test) . " /dev/" . escapeshellarg($targetdev)));
119
?>
120
		<div class="panel  panel-default">
121
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Test Results')?></h2></div>
122
			<div class="panel-body">
123
				<pre><?=$output?></pre>
124
			</div>
125
		</div>
126

    
127
		<form action="diag_smart.php" method="post" name="abort">
128
			<input type="hidden" name="device" value="<?=$targetdev?>" />
129
			<input type="hidden" name="action" value="abort" />
130
			<nav class="action-buttons">
131
				<button type="submit" name="submit" class="btn btn-danger" value="<?=gettext("Abort Tests")?>">
132
					<i class="fa fa-times icon-embed-btn"></i>
133
					<?=gettext("Abort Test")?>
134
				</button>
135
				<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-info">
136
					<i class="fa fa-undo icon-embed-btn"></i>
137
					<?=gettext("Back")?>
138
				</a>
139
			</nav>
140
		</form>
141

    
142
<?php
143
		break;
144
	}
145

    
146
	// Info on devices
147
	case 'info':
148
	{
149
		$type = $_POST['type'];
150

    
151
		if (!in_array($type, array_keys($info_types))) {
152
			print_info_box(gettext("Invalid info type, bailing."), 'danger');
153
			return;
154
		}
155

    
156
		$output = add_colors(shell_exec($smartctl . " -" . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
157
?>
158
		<div class="panel  panel-default">
159
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Information')?></h2></div>
160
			<div class="panel-body">
161
				<pre><?=$output?></pre>
162
			</div>
163
		</div>
164

    
165
		<nav class="action-buttons">
166
			<a href="<?=$_SERVER['PHP_SELF']?>" class="btn btn-info">
167
				<i class="fa fa-undo icon-embed-btn"></i>
168
				<?=gettext("Back")?>
169
			</a>
170
		</nav>
171
<?php
172
		break;
173
	}
174

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

    
184
		$output = add_colors(shell_exec($smartctl . " -l " . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
185
?>
186
		<div class="panel  panel-default">
187
			<div class="panel-heading"><h2 class="panel-title"><?=gettext('Logs')?></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
	// 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
	// Default page, prints the forms to view info, test, etc...
219
	default: {
220
// Information
221
		$devs = get_smart_drive_list();
222

    
223
		$form = new Form(false);
224

    
225
		$btnview = new Form_Button(
226
			'submit',
227
			'View',
228
			null,
229
			'fa-file-text-o'
230
		);
231
		$btnview->addClass('btn-primary');
232
		$btnview->setAttribute('id');
233

    
234
		$section = new Form_Section('Information');
235
		$group = new Form_Group('Select a drive and type:');
236
		$form->addGlobal(new Form_Input(
237
			'action',
238
			null,
239
			'hidden',
240
			'info'
241
		))->setAttribute('id');
242

    
243
		$group->add(new Form_Select(
244
			'device',
245
			'Device: /dev/',
246
			false,
247
			array_combine($devs, $devs)
248
		))->setHelp(gettext("Device: /dev/"));
249

    
250
		$group->add(new Form_Select(
251
			'type',
252
			'Type',
253
			false,
254
			$info_types
255
		))->setHelp(gettext("Information Type"));
256

    
257
		$group->add(new Form_StaticText(
258
			'',
259
			$btnview
260
		));
261
		$section->add($group);
262
		$form->add($section);
263
		print($form);
264

    
265
// Logs
266
		$form = new Form(false);
267

    
268
		$btnview =  new Form_Button(
269
			'submit',
270
			'View',
271
			null,
272
			'fa-file-text-o'
273
		);
274
		$btnview->addClass('btn-primary');
275
		$btnview->setAttribute('id');
276

    
277
		$section = new Form_Section('View Logs');
278
		$group = new Form_Group('Select a device and log');
279
		$form->addGlobal(new Form_Input(
280
			'action',
281
			null,
282
			'hidden',
283
			'logs'
284
		))->setAttribute('id');
285

    
286
		$group->add(new Form_Select(
287
			'device',
288
			'Device: /dev/',
289
			false,
290
			array_combine($devs, $devs)
291
		))->setHelp(gettext("Device: /dev/"));
292

    
293
		$group->add(new Form_Select(
294
			'type',
295
			'Log',
296
			false,
297
			$log_types
298
		))->setHelp(gettext("Log"));
299

    
300
		$group->add(new Form_StaticText(
301
			'',
302
			$btnview
303
		));
304

    
305
		$section->add($group);
306
		$form->add($section);
307
		print($form);
308

    
309
// Tests
310
		$form = new Form(false);
311

    
312
		$btntest = new Form_Button(
313
			'submit',
314
			'Test',
315
			null,
316
			'fa-wrench'
317
		);
318
		$btntest->addClass('btn-primary');
319
		$btntest->setAttribute('id');
320

    
321
		$section = new Form_Section('Perform self-tests');
322
		$group = new Form_Group('Select a drive and test');
323
		$form->addGlobal(new Form_Input(
324
			'action',
325
			null,
326
			'hidden',
327
			'test'
328
		))->setAttribute('id');
329

    
330
		$group->add(new Form_Select(
331
			'device',
332
			'Device: /dev/',
333
			false,
334
			array_combine($devs, $devs)
335
		))->setHelp(gettext("Device: /dev/"));
336

    
337
		$group->add(new Form_Select(
338
			'type',
339
			'Test',
340
			false,
341
			$test_types
342
		))->setHelp(gettext("Self-Test Type"));
343

    
344
		$group->add(new Form_StaticText(
345
			'',
346
			$btntest
347
		));
348

    
349
		$group->setHelp('Select "Conveyance" for ATA disks only.');
350
		$section->add($group);
351
		$form->add($section);
352
		print($form);
353

    
354
// Abort
355
		$btnabort = new Form_Button(
356
			'submit',
357
			'Abort Tests',
358
			null,
359
			'fa-times'
360
		);
361

    
362
		$btnabort->addClass('btn-danger')->setAttribute('id');
363

    
364
		$form = new Form(false);
365

    
366
		$section = new Form_Section('Abort Tests');
367

    
368
		$form->addGlobal(new Form_Input(
369
			'action',
370
			null,
371
			'hidden',
372
			'abort'
373
		))->setAttribute('id');
374

    
375
		$section->addInput(new Form_Select(
376
			'device',
377
			'Device: /dev/',
378
			false,
379
			array_combine($devs, $devs)
380
		))->setHelp(gettext("Aborts all self-tests running on the selected device."));
381

    
382
		$section->addInput(new Form_StaticText(
383
			'',
384
			$btnabort
385
		));
386

    
387
		$form->add($section);
388
		print($form);
389

    
390
		break;
391
	}
392
}
393

    
394
include("foot.inc");
(29-29/230)