Smart refactoring (#1081)

Smart plugin uses MVC. Changes agreed with Smart-Soft.
This commit is contained in:
Sergey Kirpa
2019-01-13 16:44:51 +01:00
committed by Franco Fichtner
parent e0a5227f77
commit 50d6842989
11 changed files with 607 additions and 331 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
PLUGIN_NAME= smart
PLUGIN_VERSION= 1.5
PLUGIN_VERSION= 2.0.d
PLUGIN_COMMENT= SMART tools
PLUGIN_DEPENDS= smartmontools
PLUGIN_MAINTAINER= franco@opnsense.org
@@ -0,0 +1,143 @@
<?php
/*
Copyright (C) 2018 Smart-Soft
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Smart\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Core\Backend;
class ServiceController extends ApiControllerBase
{
private function getDevices ()
{
$backend = new Backend();
$devices = preg_split ("/[\s]+/", trim($backend->configdRun("smart list")));
return $devices;
}
public function listAction ()
{
if ($this->request->isPost())
return array("devices" => $this->getDevices ());
return array("message" => "Unable to run list action");
}
public function infoAction ()
{
if ($this->request->isPost()) {
$device = $this->request->getPost ('device');
$type = $this->request->getPost ('type');
if (!in_array ($device, $this->getDevices ()))
return array("message" => "Invalid device name");
$valid_info_types = array("i", "H", "c", "A", "a");
if (!in_array ($type, $valid_info_types))
return array("message" => "Invalid info type");
$backend = new Backend();
$output = $backend->configdpRun("smart", array("info", $type, "/dev/".$device));
return array("output" => $output);
}
return array("message" => "Unable to run info action");
}
public function logsAction ()
{
if ($this->request->isPost()) {
$device = $this->request->getPost ('device');
$type = $this->request->getPost ('type');
if (!in_array ($device, $this->getDevices ()))
return array("message" => "Invalid device name");
$valid_log_types = array("error", "selftest");
if (!in_array ($type, $valid_log_types))
return array("message" => "Invalid log type");
$backend = new Backend();
$output = $backend->configdpRun("smart", array("log", $type, "/dev/".$device));
return array("output" => $output);
}
return array("message" => "Unable to run logs action");
}
public function testAction ()
{
if ($this->request->isPost()) {
$device = $this->request->getPost ('device');
$type = $this->request->getPost ('type');
if (!in_array ($device, $this->getDevices ()))
return array("message" => "Invalid device name");
$valid_test_types = array("offline", "short", "long", "conveyance");
if (!in_array ($type, $valid_test_types))
return array("message" => "Invalid test type");
$backend = new Backend();
$output = $backend->configdpRun("smart", array("test", $type, "/dev/".$device));
return array("output" => $output);
}
return array("message" => "Unable to run test action");
}
public function abortAction ()
{
if ($this->request->isPost()) {
$device = $this->request->getPost ('device');
if (!in_array ($device, $this->getDevices ()))
return array("message" => "Invalid device name");
$backend = new Backend();
$output = $backend->configdpRun("smart", array("abort", "/dev/".$device));
return array("output" => $output);
}
return array("message" => "Unable to run abort action");
}
}
@@ -0,0 +1,38 @@
<?php
/*
Copyright (C) 2018 Smart-Soft
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Smart;
class IndexController extends \OPNsense\Base\IndexController
{
public function indexAction()
{
// pick the template to serve to our users.
$this->view->pick('OPNsense/Smart/index');
}
}
@@ -2,7 +2,8 @@
<page-services-smart>
<name>Services: SMART</name>
<patterns>
<pattern>diag_smart.php*</pattern>
<pattern>ui/smart/*</pattern>
<pattern>api/smart/*</pattern>
</patterns>
</page-services-smart>
</acl>
@@ -1,5 +1,5 @@
<menu>
<Services>
<SMART url="/diag_smart.php" cssClass="fa fa-stethoscope fa-fw"/>
<SMART url="/ui/smart" cssClass="fa fa-stethoscope fa-fw"/>
</Services>
</menu>
@@ -0,0 +1,260 @@
{#
Copyright (C) 2018 Smart-Soft
Copyright (C) 2014 Deciso B.V.
Copyright (C) 2010 Jim Pingle <jimp@pfsense.org>
Copyright (C) 2006 Eric Friesen
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
#}
<script type="text/javascript">
// Highlights the words "PASSED", "FAILED", and "WARNING".
function add_colors(text) {
return text
.replace(/PASSED/g, '<span class="text-success">{{ lang._("PASSED") }}</span>')
.replace(/FAILED/g, '<span class="text-danger">{{ lang._("FAILED") }}</span>')
.replace(/WARNING/g, '<span class="text-warning">{{ lang._("WARNING") }}</span>');
};
// Appends options to select device.
function appendDeviceSelectOptions(deviceSelect, devices) {
$.each(devices, function(index, value) {
deviceSelect
.append($("<option></option>")
.attr("value", value)
.text(value));
});
};
$( document ).ready(function() {
ajaxCall("/api/smart/service/list", {}, function(data, status) {
// action to run after reload
var devices = data.devices;
if (Array.isArray(devices) && devices.length > 0) {
$("#noDevicesMsg").addClass("hidden");
$("#genericActions").removeClass("hidden");
appendDeviceSelectOptions($("#device1"), devices);
appendDeviceSelectOptions($("#device2"), devices);
appendDeviceSelectOptions($("#device3"), devices);
appendDeviceSelectOptions($("#device4"), devices);
$("#viewInfoAct").click(function() {
var type = $("input[name='type']:checked").val();
var device = $("#device1").val();
ajaxCall("/api/smart/service/info", {
"type" : type,
"device" : device
}, function(data, status) {
$("#infoMsg").html(add_colors(data['output']));
$("#infoMsg").removeClass("hidden");
});
});
$("#testAct").click(function() {
var type = $("input[name='testType']:checked").val();
var device = $("#device2").val();
ajaxCall("/api/smart/service/test", {
"type" : type,
"device" : device
}, function(data, status) {
$("#testMsg").html(add_colors(data['output']));
$("#testMsg").removeClass("hidden");
});
});
$("#viewLogsAct").click(function() {
var type = $("input[name='logType']:checked").val();
var device = $("#device3").val();
ajaxCall("/api/smart/service/logs", {
"type" : type,
"device" : device
}, function(data, status) {
$("#logsMsg").html(add_colors(data['output']));
$("#logsMsg").removeClass("hidden");
});
});
$("#abortTestAct").click(function() {
if (!confirm("{{ lang._('Do you really want to abort the test?') }}"))
return;
var device = $("#device4").val();
ajaxCall("/api/smart/service/abort", {
"device" : device
}, function(data, status) {
$("#abortTestMsg").html(data['output']);
$("#abortTestMsg").removeClass("hidden");
});
});
} else {
$("#noDevicesMsg").removeClass("hidden");
$("#genericActions").addClass("hidden");
}
})
});
</script>
<div class="alert alert-info hidden" role="alert" id="noDevicesMsg">
{{ lang._('No SMART devices.') }}
</div>
<div class="row hidden" id="genericActions">
<section class="col-xs-12">
<div class="content-box tab-content table-responsive">
<table class="table table-striped __nomb">
<tr>
<th colspan="2" style="vertical-align:top" class="listtopic">{{ lang._('Info') }}</th>
</tr>
<tr>
<td>{{ lang._('Info type') }}</td>
<td><div class="radio">
<label><input type="radio" name="type" value="i" />{{ lang._('Info') }}</label>&nbsp;
<label><input type="radio" name="type" value="H" checked="checked" />{{ lang._('Health') }}</label>&nbsp;
<label><input type="radio" name="type" value="c" />{{ lang._('SMART Capabilities') }}</label>&nbsp;
<label><input type="radio" name="type" value="A" />{{ lang._('Attributes') }}</label>&nbsp;
<label><input type="radio" name="type" value="a" />{{ lang._('All') }}</label>
</div>
</td>
</tr>
<tr>
<td><label for="device1">{{ lang._('Device: /dev/') }}</label></td>
<td >
<select id="device1" name="device" class="form-control">
</select>
</td>
</tr>
<tr>
<td style="width:22%; vertical-align:top">&nbsp;</td>
<td style="width:78%">
<input type="button" name="submit" class="btn btn-primary" value="{{ lang._('View') }}" id="viewInfoAct" />
</td>
</tr>
</table>
</div>
<pre class="hidden" id="infoMsg">
</pre>
</section>
<section class="col-xs-12">
<div class="content-box tab-content table-responsive">
<table class="table table-striped __nomb">
<tr>
<th colspan="2" style="vertical-align:top" class="listtopic">{{ lang._('Perform Self-tests') }}</th>
</tr>
<tr>
<td>{{ lang._('Test type') }}</td>
<td>
<div class="radio">
<label><input type="radio" name="testType" value="offline" />{{ lang._('Offline') }}</label>&nbsp;
<label><input type="radio" name="testType" value="short" checked="checked" />{{ lang._('Short') }}</label>&nbsp;
<label><input type="radio" name="testType" value="long" />{{ lang._('Long') }}</label>&nbsp;
<label><input type="radio" name="testType" value="conveyance" />{{ lang._('Conveyance (ATA Disks Only)') }}</label>
</div>
</td>
</tr>
<tr>
<td><label for="device2">{{ lang._('Device: /dev/') }}</label></td>
<td>
<select id="device2" name="device" class="form-control">
</select>
</td>
</tr>
<tr>
<td style="width:22%; vertical-align:top">&nbsp;</td>
<td style="width:78%">
<input type="button" name="submit" class="btn btn-primary" value="{{ lang._('Test') }}" id="testAct" />
</td>
</tr>
</table>
</div>
<pre class="hidden" id="testMsg">
</pre>
</section>
<section class="col-xs-12">
<div class="content-box tab-content table-responsive">
<table class="table table-striped __nomb">
<tr>
<th colspan="2" style="vertical-align:top" class="listtopic">{{ lang._('View Logs') }}</th>
</tr>
<tr>
<td>{{ lang._('Log type') }}</td>
<td>
<div class="radio">
<label><input type="radio" name="logType" value="error" checked="checked" />{{ lang._('Error') }}</label>&nbsp;
<label><input type="radio" name="logType" value="selftest" />{{ lang._('Self-test') }}</label>
</div>
</td>
</tr>
<tr>
<td><label for="device3">{{ lang._('Device: /dev/') }}</label></td>
<td >
<select id="device3" name="device" class="form-control">
</select>
</td>
</tr>
<tr>
<td style="width:22%; vertical-align:top">&nbsp;</td>
<td style="width:78%">
<input type="button" name="submit" class="btn btn-primary" value="{{ lang._('View') }}" id="viewLogsAct" />
</td>
</tr>
</table>
</div>
<pre class="hidden" id="logsMsg">
</pre>
</section>
<section class="col-xs-12">
<div class="content-box tab-content table-responsive">
<table class="table table-striped __nomb">
<tr>
<th colspan="2" style="vertical-align:top" class="listtopic">{{ lang._('Abort tests') }}</th>
</tr>
<tr>
<td><label for="device4">{{ lang._('Device: /dev/') }}</label></td>
<td >
<select id="device4" name="device" class="form-control">
</select>
</td>
</tr>
<tr>
<td style="width:22%; vertical-align:top">&nbsp;</td>
<td style="width:78%">
<input type="button" name="submit" value="{{ lang._('Abort') }}" class="btn btn-primary" id="abortTestAct" />
</td>
</tr>
</table>
</div>
<pre class="hidden" id="abortTestMsg">
</pre>
</section>
</div>
@@ -0,0 +1,43 @@
#!/bin/sh
# Copyright (C) 2018 Smart-Soft
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
result=""
for dev in `ls /dev | grep '^\(ad\|da\|ada\)[0-9]\{1,2\}$'`; do
ident=`/usr/sbin/diskinfo -v $dev | grep ident | awk '{print $1}'`;
state=`/usr/local/sbin/smartctl -H $dev | awk -F: '
/^SMART overall-health self-assessment test result/ {print $2;exit}
/^SMART Health Status/ {print $2;exit}'`;
if [ -n "$result" ]; then
result="$result,";
fi
result="$result{\"device\":\"$dev\",\"ident\":\"$ident\",\"state\":\"$state\"}";
done
echo "[$result]"
@@ -0,0 +1,97 @@
[list]
command:/bin/ls /dev | grep '^\(ad\|da\|ada\)[0-9]\{1,2\}$'
parameters:
type:script_output
message:list installed devices
description:Get all IDE and SCSI devices currently installed
[detailed.list]
command:/usr/local/opnsense/scripts/OPNsense/smart/detailed_list.sh
parameters:
type:script_output
message:list installed devices
description:Get all IDE and SCSI devices currently installed
[info.i]
command:/usr/local/sbin/smartctl -i
parameters:%s; exit 0
type:script_output
message:Get identity info for device %s
description:Get identity info for devices
[info.H]
command:/usr/local/sbin/smartctl -H
parameters:%s; exit 0
type:script_output
message:Get SMART health status info for device %s
description:Get SMART health status info for devices
[info.c]
command:/usr/local/sbin/smartctl -c
parameters:%s; exit 0
type:script_output
message:Get capabilities for device %s
description:Get capabilities for devices
[info.A]
command:/usr/local/sbin/smartctl -A
parameters:%s; exit 0
type:script_output
message:Get vendor-specific attributes for device %s
description:Get vendor-specific attributes for devices
[info.a]
command:/usr/local/sbin/smartctl -a
parameters:%s; exit 0
type:script_output
message:Get all SMART info for device %s
description:Get info for devices
[log.error]
command:/usr/local/sbin/smartctl -l error
parameters:%s; exit 0
type:script_output
message:Get error log for device %s
description:Get error logs for devices
[log.selftest]
command:/usr/local/sbin/smartctl -l selftest
parameters:%s; exit 0
type:script_output
message:Get selftest log for device %s
description:Get selftest logs for devices
[test.offline]
command:/usr/local/sbin/smartctl -t offline
parameters:%s; exit 0
type:script_output
message:Testing device %s (offline)
description:Testing devices
[test.short]
command:/usr/local/sbin/smartctl -t short
parameters:%s; exit 0
type:script_output
message:Testing device %s (short)
description:Testing devices
[test.long]
command:/usr/local/sbin/smartctl -t long
parameters:%s; exit 0
type:script_output
message:Testing device %s (long)
description:Testing devices
[test.conveyance]
command:/usr/local/sbin/smartctl -t conveyance
parameters:%s; exit 0
type:script_output
message:Testing device %s (conveyance)
description:Testing devices
[abort]
command:/usr/local/sbin/smartctl -X
parameters:%s; exit 0
type:script_output
message:Abort test on device %s
description:Abort tests on devices
-299
View File
@@ -1,299 +0,0 @@
<?php
/*
Copyright (C) 2014 Deciso B.V.
Copyright (C) 2010 Jim Pingle <jimp@pfsense.org>
Copyright (C) 2006 Eric Friesen
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
require_once("guiconfig.inc");
$smartctl = "/usr/local/sbin/smartctl";
$valid_test_types = array("offline", "short", "long", "conveyance");
$valid_info_types = array("i", "H", "c", "A", "a");
$valid_log_types = array("error", "selftest");
include("head.inc");
?>
<body>
<?php
include("fbegin.inc");
?>
<section class="page-content-main">
<div class="container-fluid">
<div class="row">
<section class="col-xs-12">
<?php
// Highlights the words "PASSED", "FAILED", and "WARNING".
function add_colors($string)
{
// To add words keep arrayes matched by numbers
$patterns[0] = '/PASSED/';
$patterns[1] = '/FAILED/';
$patterns[2] = '/Warning/';
$replacements[0] = '<span class="text-success">' . gettext("PASSED") . '</span>';
$replacements[1] = '<span class="text-danger">' . gettext("FAILED") . '</span>';
$replacements[2] = '<span class="text-warning>' . gettext("WARNING") . '</span>';
ksort($patterns);
ksort($replacements);
return preg_replace($patterns, $replacements, $string);
}
// What page, aka. action is being wanted
// If they "get" a page but don't pass all arguments, smartctl will throw an error
$action = (isset($_POST['action']) ? $_POST['action'] : $_GET['action']);
$targetdev = basename($_POST['device']);
if (!file_exists('/dev/' . $targetdev)) {
echo gettext("Device does not exist, bailing.");
return;
}
switch($action) {
// Testing devices
case 'test':
$test = $_POST['testType'];
if (!in_array($test, $valid_test_types)) {
echo gettext("Invalid test type, bailing.");
return;
}
$output = add_colors(shell_exec($smartctl . " -t " . escapeshellarg($test) . " /dev/" . escapeshellarg($targetdev)));
echo '<pre>' . $output . '
<form action="diag_smart.php" method="post" name="abort">
<input type="hidden" name="device" value="' . html_safe($targetdev) . '" />
<input type="hidden" name="action" value="abort" />
<input type="submit" name="submit" value="' . html_safe(gettext("Abort")) . '" />
</form>
</pre>';
break;
// Info on devices
case 'info':
$type = $_POST['type'];
if (!in_array($type, $valid_info_types)) {
echo gettext("Invalid info type, bailing.");
return;
}
$output = add_colors(shell_exec($smartctl . " -" . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
echo "<pre>$output</pre>";
break;
// View logs
case 'logs':
$type = $_POST['type'];
if (!in_array($type, $valid_log_types)) {
echo gettext("Invalid log type, bailing.");
return;
}
$output = add_colors(shell_exec($smartctl . " -l " . escapeshellarg($type) . " /dev/" . escapeshellarg($targetdev)));
echo "<pre>$output</pre>";
break;
// Abort tests
case 'abort':
$output = shell_exec($smartctl . " -X /dev/" . escapeshellarg($targetdev));
echo "<pre>$output</pre>";
break;
// Default page, prints the forms to view info, test, etc...
default:
// Get all AD* and DA* (IDE and SCSI) devices currently installed and stores them in the $devs array
exec("ls /dev | grep '^\(ad\|da\|ada\)[0-9]\{1,2\}$'", $devs);
if (count($devs) > 0):
?>
<div class="content-box tab-content table-responsive">
<form action="<?= html_safe($_SERVER['PHP_SELF']) ?>" method="post" name="iform" id="iform">
<table class="table table-striped __nomb">
<tr>
<th colspan="2" style="vertical-align:top" class="listtopic"><?=gettext('Info'); ?></th>
</tr>
<tr>
<td><?= gettext("Info type") ?></td>
<td><div class="radio">
<label><input type="radio" name="type" value="i" /><?=gettext("Info"); ?></label>&nbsp;
<label><input type="radio" name="type" value="H" checked="checked" /><?=gettext("Health"); ?></label>&nbsp;
<label><input type="radio" name="type" value="c" /><?=gettext("SMART Capabilities"); ?></label>&nbsp;
<label><input type="radio" name="type" value="A" /><?=gettext("Attributes"); ?></label>&nbsp;
<label><input type="radio" name="type" value="a" /><?=gettext("All"); ?></label>
</div>
</td>
</tr>
<tr>
<td><label for="device1"><?=gettext("Device: /dev/"); ?></label></td>
<td >
<select id="device1" name="device" class="form-control">
<?php foreach($devs as $dev) {
echo "<option value=\"" . $dev . "\">" . $dev . "</option>";
} ?>
</select>
</td>
</tr>
<tr>
<td style="width:22%; vertical-align:top">&nbsp;</td>
<td style="width:78%">
<input type="hidden" name="action" value="info" />
<input type="submit" name="submit" class="btn btn-primary" value="<?=gettext("View"); ?>" />
</td>
</tr>
</table>
</form>
</div>
</section>
<section class="col-xs-12">
<div class="content-box tab-content table-responsive">
<form action="<?= html_safe($_SERVER['PHP_SELF']) ?>" method="post" name="test" id="iform">
<table class="table table-striped __nomb">
<tr>
<th colspan="2" style="vertical-align:top" class="listtopic"><?=gettext('Perform Self-tests'); ?></th>
</tr>
<tr>
<td><?=gettext("Test type"); ?></td>
<td>
<div class="radio">
<label><input type="radio" name="testType" value="offline" /><?=gettext("Offline"); ?></label>&nbsp;
<label><input type="radio" name="testType" value="short" checked="checked" /><?=gettext("Short"); ?></label>&nbsp;
<label><input type="radio" name="testType" value="long" /><?=gettext("Long"); ?></label>&nbsp;
<label><input type="radio" name="testType" value="conveyance" /><?=gettext("Conveyance (ATA Disks Only)"); ?></label>
</div>
</td>
</tr>
<tr>
<td><label for="device2"><?=gettext("Device: /dev/"); ?></label></td>
<td>
<select id="device2" name="device" class="form-control">
<?php foreach($devs as $dev) {
echo "<option value=\"$dev\">$dev</option>";
} ?>
</select>
</td>
</tr>
<tr>
<td style="width:22%; vertical-align:top">&nbsp;</td>
<td style="width:78%">
<input type="hidden" name="action" value="test" />
<input type="submit" name="submit" class="btn btn-primary" value="<?=gettext("Test"); ?>" />
</td>
</tr>
</table>
</form>
</div>
</section>
<section class="col-xs-12">
<div class="content-box tab-content table-responsive">
<form action="<?= html_safe($_SERVER['PHP_SELF']) ?>" method="post" name="logs" id="iform">
<table class="table table-striped __nomb">
<tr>
<th colspan="2" style="vertical-align:top" class="listtopic"><?=gettext('View Logs'); ?></th>
</tr>
<tr>
<td><?= gettext("Log type"); ?></td>
<td>
<div class="radio">
<label><input type="radio" name="type" value="error" checked="checked" /><?=gettext("Error"); ?></label>&nbsp;
<label><input type="radio" name="type" value="selftest" /><?=gettext("Self-test"); ?></label>
</div>
</td>
</tr>
<tr>
<td><label for="device3"><?=gettext("Device: /dev/"); ?></label></td>
<td >
<select id="device3" name="device" class="form-control">
<?php foreach($devs as $dev) {
echo "<option value=\"$dev\">$dev</option>";
} ?>
</select>
</td>
</tr>
<tr>
<td style="width:22%; vertical-align:top">&nbsp;</td>
<td style="width:78%">
<input type="hidden" name="action" value="logs" />
<input type="submit" name="submit" class="btn btn-primary" value="<?=gettext("View"); ?>" />
</td>
</tr>
</table>
</form>
</div>
</section>
<section class="col-xs-12">
<div class="content-box tab-content table-responsive">
<form action="<?= html_safe($_SERVER['PHP_SELF']) ?>" method="post" name="abort" id="iform">
<table class="table table-striped __nomb">
<tr>
<th colspan="2" style="vertical-align:top" class="listtopic"><?= gettext('Abort tests'); ?></th>
</tr>
<tr>
<td><label for="device4"><?=gettext("Device: /dev/"); ?></label></td>
<td >
<select id="device4" name="device" class="form-control">
<?php foreach($devs as $dev) {
echo "<option value=\"$dev\">$dev</option>";
} ?>
</select>
</td>
</tr>
<tr>
<td style="width:22%; vertical-align:top">&nbsp;</td>
<td style="width:78%">
<input type="hidden" name="action" value="logs" />
<input type="submit" name="submit" value="<?=html_safe(gettext("Abort")) ?>" class="btn btn-primary"
onclick="return confirm('<?=gettext("Do you really want to abort the test?"); ?>')" />
</td>
</tr>
</table>
</form>
</div>
</section>
<?php
else:
echo gettext("No SMART devices.");
endif;
break;
}
// print back button on pages
if(isset($_POST['submit']) && $_POST['submit'] != "Save") {
echo '<br /><a class="btn btn-primary" href="' . html_safe($_SERVER['PHP_SELF']) . '">' . gettext("Back") . '</a>';
}
?>
</section>
<?php include("foot.inc"); ?>
@@ -1,4 +1,4 @@
<?php
//set variable for custom title
$smart_status_title = "SMART Status";
$smart_status_title_link = "diag_smart.php";
$smart_status_title_link = "ui/smart";
@@ -1,6 +1,7 @@
<?php
/*
* Copyright (C) 2018 Smart-Soft
* Copyright (C) 2014 Deciso B.V.
* Copyright 2012 mkirbst @ pfSense Forum
* All rights reserved.
@@ -40,40 +41,32 @@ require_once("widgets/include/smart_status.inc");
</tr>
<?php
$devs = array();
## Get all adX, daX, and adaX (IDE, SCSI, and AHCI) devices currently installed
exec("ls /dev | grep '^\(ad\|da\|ada\)[0-9]\{1,2\}$'", $devs); ## From SMART status page
$devs = json_decode (configd_run ("smart detailed list"));
if (count($devs) > 0) {
foreach ($devs as $dev) {
## for each found drive do
$dev_ident = exec("diskinfo -v /dev/$dev | grep ident | awk '{print $1}'"); ## get identifier from drive
$dev_state = trim(exec("smartctl -H /dev/$dev | awk -F: '/^SMART overall-health self-assessment test result/ {print $2;exit}
/^SMART Health Status/ {print $2;exit}'")); ## get SMART state from drive
$dev_state_translated = "";
switch ($dev_state) {
case "PASSED":
case "OK":
$dev_state_translated = gettext('OK');
$color = "success";
break;
case "":
$dev_state = "Unknown";
$dev_state_translated = gettext('Unknown');
$color = "warning";
break;
default:
$color = "danger";
break;
}
foreach ($devs as $dev) {
$dev_state_translated = "";
switch ($dev->state) {
case "PASSED":
case "OK":
$dev_state_translated = gettext('OK');
$color = "success";
break;
case "":
$dev_state_translated = gettext('Unknown');
$color = "warning";
break;
default:
$color = "danger";
break;
}
?>
<tr>
<td><?= $dev ?></td>
<td style="text-align:center"><?= $dev_ident ?></td>
<td><?= $dev->device ?></td>
<td style="text-align:center"><?= $dev->ident ?></td>
<td style="text-align:center"><span class="label label-<?= $color ?>">&nbsp;<?= $dev_state_translated ?>&nbsp;</span></td>
</tr>
<?php
}
}
?>
</table>