mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Human readable database inconsistent error (#12950)
* Human readable database inconsistent error In case a db error causes an exception, check validate and show the db errors to the user in the webui. * only failed validations * fix style
This commit is contained in:
86
LibreNMS/Exceptions/DatabaseInconsistentException.php
Normal file
86
LibreNMS/Exceptions/DatabaseInconsistentException.php
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* DatabaseVersionTooLow.php
|
||||||
|
*
|
||||||
|
* -Description-
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @package LibreNMS
|
||||||
|
* @link http://librenms.org
|
||||||
|
* @copyright 2021 Tony Murray
|
||||||
|
* @author Tony Murray <murraytony@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace LibreNMS\Exceptions;
|
||||||
|
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
|
use LibreNMS\Interfaces\Exceptions\UpgradeableException;
|
||||||
|
use LibreNMS\ValidationResult;
|
||||||
|
use LibreNMS\Validations\Database;
|
||||||
|
use LibreNMS\Validator;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class DatabaseInconsistentException extends \Exception implements UpgradeableException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \LibreNMS\ValidationResult[]
|
||||||
|
*/
|
||||||
|
private $validationResults;
|
||||||
|
|
||||||
|
public function __construct($validationResults, $message = '', $code = 0, Throwable $previous = null)
|
||||||
|
{
|
||||||
|
$this->validationResults = $validationResults;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function upgrade($exception)
|
||||||
|
{
|
||||||
|
if ($exception instanceof QueryException || $exception->getPrevious() instanceof QueryException) {
|
||||||
|
$validator = new Validator();
|
||||||
|
(new Database())->validate($validator);
|
||||||
|
|
||||||
|
// get only failed results
|
||||||
|
$results = array_filter($validator->getResults('database'), function (ValidationResult $result) {
|
||||||
|
return $result->getStatus() === ValidationResult::FAILURE;
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($results) {
|
||||||
|
return new static($results, $exception->getMessage(), $exception->getCode(), $exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the exception into an HTTP or JSON response.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
public function render(\Illuminate\Http\Request $request)
|
||||||
|
{
|
||||||
|
$message = trans('exceptions.database_inconsistent.title');
|
||||||
|
if (isset($this->validationResults[0])) {
|
||||||
|
$message .= ': ' . $this->validationResults[0]->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $request->wantsJson() ? response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => $message,
|
||||||
|
]) : response()->view('errors.db_inconsistent', [
|
||||||
|
'results' => $this->validationResults,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@@ -106,16 +106,16 @@ class Database extends BaseValidation
|
|||||||
if (version_compare($version[0], self::MARIADB_MIN_VERSION, '<=')) {
|
if (version_compare($version[0], self::MARIADB_MIN_VERSION, '<=')) {
|
||||||
$validator->fail(
|
$validator->fail(
|
||||||
'MariaDB version ' . self::MARIADB_MIN_VERSION . ' is the minimum supported version as of ' .
|
'MariaDB version ' . self::MARIADB_MIN_VERSION . ' is the minimum supported version as of ' .
|
||||||
self::MARIADB_MIN_VERSION_DATE . '. Update MariaDB to a supported version ' .
|
self::MARIADB_MIN_VERSION_DATE . '.',
|
||||||
self::MARIADB_RECOMMENDED_VERSION . ' suggested).'
|
'Update MariaDB to a supported version, ' . self::MARIADB_RECOMMENDED_VERSION . ' suggested.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (version_compare($version[0], self::MYSQL_MIN_VERSION, '<=')) {
|
if (version_compare($version[0], self::MYSQL_MIN_VERSION, '<=')) {
|
||||||
$validator->fail(
|
$validator->fail(
|
||||||
'MySQL version ' . self::MYSQL_MIN_VERSION . ' is the minimum supported version as of ' .
|
'MySQL version ' . self::MYSQL_MIN_VERSION . ' is the minimum supported version as of ' .
|
||||||
self::MYSQL_MIN_VERSION_DATE . '. Update MySQL to a supported version (' .
|
self::MYSQL_MIN_VERSION_DATE . '.',
|
||||||
self::MYSQL_RECOMMENDED_VERSION . ' suggested).'
|
'Update MySQL to a supported version, ' . self::MYSQL_RECOMMENDED_VERSION . ' suggested.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -118,7 +118,7 @@ class Validator
|
|||||||
* Get the ValidationResults for a specific validation group.
|
* Get the ValidationResults for a specific validation group.
|
||||||
*
|
*
|
||||||
* @param string $validation_group
|
* @param string $validation_group
|
||||||
* @return array
|
* @return ValidationResult[]
|
||||||
*/
|
*/
|
||||||
public function getResults($validation_group = null)
|
public function getResults($validation_group = null)
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Exceptions;
|
namespace App\Exceptions;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
@@ -33,6 +32,7 @@ class Handler extends ExceptionHandler
|
|||||||
\LibreNMS\Exceptions\DuskUnsafeException::class,
|
\LibreNMS\Exceptions\DuskUnsafeException::class,
|
||||||
\LibreNMS\Exceptions\UnserializableRouteCache::class,
|
\LibreNMS\Exceptions\UnserializableRouteCache::class,
|
||||||
\LibreNMS\Exceptions\MaximumExecutionTimeExceeded::class,
|
\LibreNMS\Exceptions\MaximumExecutionTimeExceeded::class,
|
||||||
|
\LibreNMS\Exceptions\DatabaseInconsistentException::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
public function render($request, Throwable $exception)
|
public function render($request, Throwable $exception)
|
||||||
|
@@ -79,11 +79,10 @@ class DatabaseController extends InstallationController implements InstallerStep
|
|||||||
(new Database())->validateSystem($validator);
|
(new Database())->validateSystem($validator);
|
||||||
$results = $validator->getResults('database');
|
$results = $validator->getResults('database');
|
||||||
|
|
||||||
/** @var \LibreNMS\ValidationResult $result */
|
|
||||||
foreach ($results as $result) {
|
foreach ($results as $result) {
|
||||||
if ($result->getStatus() == ValidationResult::FAILURE) {
|
if ($result->getStatus() == ValidationResult::FAILURE) {
|
||||||
$ok = false;
|
$ok = false;
|
||||||
$messages[] = $result->getMessage();
|
$messages[] = $result->getMessage() . ' ' . $result->getFix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
@@ -4,6 +4,10 @@ return [
|
|||||||
'database_connect' => [
|
'database_connect' => [
|
||||||
'title' => 'Error connecting to database',
|
'title' => 'Error connecting to database',
|
||||||
],
|
],
|
||||||
|
'database_inconsistent' => [
|
||||||
|
'title' => 'Database inconsistent',
|
||||||
|
'header' => 'Database inconsistencies found during a database error, please fix to continue.',
|
||||||
|
],
|
||||||
'dusk_unsafe' => [
|
'dusk_unsafe' => [
|
||||||
'title' => 'It is unsafe to run Dusk in production',
|
'title' => 'It is unsafe to run Dusk in production',
|
||||||
'message' => 'Run ":command" to remove Dusk or if you are a developer set the appropriate APP_ENV',
|
'message' => 'Run ":command" to remove Dusk or if you are a developer set the appropriate APP_ENV',
|
||||||
|
20
resources/views/errors/db_inconsistent.blade.php
Normal file
20
resources/views/errors/db_inconsistent.blade.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
@extends('layouts.error')
|
||||||
|
|
||||||
|
@section('title')
|
||||||
|
@lang('exceptions.database_inconsistent.title')
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<h3>@lang('exceptions.database_inconsistent.header')</h3>
|
||||||
|
|
||||||
|
<div class="message-block">
|
||||||
|
@foreach($results as $result)
|
||||||
|
<p>
|
||||||
|
<h2>{{ $result->getMessage() }}</h2>
|
||||||
|
@if($result->hasFix())
|
||||||
|
<div style="margin-left: 3em; font-size: 18px">{{ $result->getFix() }}</div>
|
||||||
|
@endif
|
||||||
|
</p>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endsection
|
@@ -46,6 +46,8 @@
|
|||||||
.trace-method { color: #B0413E; font-weight: bold; }
|
.trace-method { color: #B0413E; font-weight: bold; }
|
||||||
.trace-arguments { color: #777; font-weight: normal; padding-left: 2px; }
|
.trace-arguments { color: #777; font-weight: normal; padding-left: 2px; }
|
||||||
|
|
||||||
|
.message-block { margin: 30px 0; }
|
||||||
|
|
||||||
hr.separator { border: 0; margin: 1.8em 0; height: 1px; background: #333 linear-gradient(to right, #ccc, #333, #ccc); }
|
hr.separator { border: 0; margin: 1.8em 0; height: 1px; background: #333 linear-gradient(to right, #ccc, #333, #ccc); }
|
||||||
|
|
||||||
@media (min-width: 575px) {
|
@media (min-width: 575px) {
|
||||||
@@ -65,7 +67,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@yield('content')
|
<div class="message-block">
|
||||||
|
@yield('content')
|
||||||
|
</div>
|
||||||
|
|
||||||
<hr class="separator"/>
|
<hr class="separator"/>
|
||||||
<p>@lang("Check your log for more details.") ({{ isset($log_file) ? $log_file : 'librenms.log' }})</p>
|
<p>@lang("Check your log for more details.") ({{ isset($log_file) ? $log_file : 'librenms.log' }})</p>
|
||||||
|
Reference in New Issue
Block a user