Project

General

Profile

Download (9.4 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-2019 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2006 Eric Friesen
8
 * All rights reserved.
9
 *
10
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 * http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22

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

    
30
require_once("guiconfig.inc");
31

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

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

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

    
45
$smartctl = "/usr/local/sbin/smartctl";
46

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

    
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] = '<span class="text-success">' . gettext("PASSED") . '</span>';
85
	$replacements[1] = '<span class="text-alert">' . gettext("FAILED") . '</span>';
86
	$replacements[2] = '<span class="text-warning">' . gettext("Warning") . '</span>';
87
	ksort($patterns);
88
	ksort($replacements);
89
	return preg_replace($patterns, $replacements, $string);
90
}
91

    
92
$targetdev = basename($_POST['device']);
93

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

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

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

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

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

    
140
<?php
141
		break;
142
	}
143

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

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

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

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

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

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

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

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

    
216
	// Default page, prints the forms to view info, test, etc...
217
	default: {
218
// Information
219
		$devs = get_smart_drive_list();
220

    
221
		$form = new Form(false);
222

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

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

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

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

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

    
263
// Logs
264
		$form = new Form(false);
265

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

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

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

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

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

    
303
		$section->add($group);
304
		$form->add($section);
305
		print($form);
306

    
307
// Tests
308
		$form = new Form(false);
309

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

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

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

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

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

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

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

    
360
		$btnabort->addClass('btn-danger')->setAttribute('id');
361

    
362
		$form = new Form(false);
363

    
364
		$section = new Form_Section('Abort Tests');
365

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

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

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

    
385
		$form->add($section);
386
		print($form);
387

    
388
		break;
389
	}
390
}
391

    
392
include("foot.inc");
(28-28/225)