Install: Validate database before migrating (#12867)
* Validate database during install Needed to remove usages of legacy functions in the validation * Fix output, restore real versions
This commit is contained in:
parent
500b0ac6fa
commit
df5096e449
|
@ -28,6 +28,7 @@ use DB;
|
|||
use Illuminate\Support\Str;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Util\Version;
|
||||
use PDOException;
|
||||
use Schema as LaravelSchema;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
|
@ -111,6 +112,25 @@ class Schema
|
|||
return $this->schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the schema version from the previous schema system
|
||||
*/
|
||||
public static function getLegacySchema(): int
|
||||
{
|
||||
try {
|
||||
$db = \LibreNMS\DB\Eloquent::DB();
|
||||
if ($db) {
|
||||
return (int) $db->table('dbSchema')
|
||||
->orderBy('version', 'DESC')
|
||||
->value('version');
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
// return default
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all tables.
|
||||
*
|
||||
|
|
|
@ -170,7 +170,7 @@ abstract class Model
|
|||
*/
|
||||
public static function onDelete($model)
|
||||
{
|
||||
if (isCli()) {
|
||||
if (\App::runningInConsole()) {
|
||||
echo '-';
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ abstract class Model
|
|||
*/
|
||||
public static function onCreate($model)
|
||||
{
|
||||
if (isCli()) {
|
||||
if (\App::runningInConsole()) {
|
||||
echo '+';
|
||||
}
|
||||
}
|
||||
|
@ -190,14 +190,14 @@ abstract class Model
|
|||
*/
|
||||
public static function onUpdate($model)
|
||||
{
|
||||
if (isCli()) {
|
||||
if (\App::runningInConsole()) {
|
||||
echo 'U';
|
||||
}
|
||||
}
|
||||
|
||||
public static function onNoUpdate()
|
||||
{
|
||||
if (isCli()) {
|
||||
if (\App::runningInConsole()) {
|
||||
echo '.';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
namespace LibreNMS\Util;
|
||||
|
||||
use App;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Proc;
|
||||
|
||||
|
@ -60,7 +61,7 @@ class Snmpsim
|
|||
|
||||
$cmd = $this->getCmd();
|
||||
|
||||
if (isCli()) {
|
||||
if (App::runningInConsole()) {
|
||||
echo "Starting snmpsim listening on {$this->ip}:{$this->port}... \n";
|
||||
d_echo($cmd);
|
||||
}
|
||||
|
@ -71,7 +72,7 @@ class Snmpsim
|
|||
sleep($wait);
|
||||
}
|
||||
|
||||
if (isCli() && ! $this->proc->isRunning()) {
|
||||
if (App::runningInConsole() && ! $this->proc->isRunning()) {
|
||||
// if starting failed, run snmpsim again and output to the console and validate the data
|
||||
passthru($this->getCmd(false) . ' --validate-data');
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ class Database extends BaseValidation
|
|||
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
if (! dbIsConnected()) {
|
||||
if (! Eloquent::isConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ class Database extends BaseValidation
|
|||
$this->checkMysqlEngine($validator);
|
||||
|
||||
// check database schema version
|
||||
$current = get_db_schema();
|
||||
$current = \LibreNMS\DB\Schema::getLegacySchema();
|
||||
$latest = 1000;
|
||||
|
||||
if ($current === 0 || $current === $latest) {
|
||||
|
@ -96,16 +96,16 @@ class Database extends BaseValidation
|
|||
if (version_compare($version[0], self::MARIADB_MIN_VERSION, '<=')) {
|
||||
$validator->fail(
|
||||
'MariaDB version ' . self::MARIADB_MIN_VERSION . ' is the minimum supported version as of ' .
|
||||
self::MARIADB_MIN_VERSION_DATE . '. We recommend you update MariaDB to a supported version ' .
|
||||
self::MARIADB_RECOMMENDED_VERSION . ' suggested). Failure to update MariaDB will eventually cause issues.'
|
||||
self::MARIADB_MIN_VERSION_DATE . '. Update MariaDB to a supported version ' .
|
||||
self::MARIADB_RECOMMENDED_VERSION . ' suggested).'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (version_compare($version[0], self::MYSQL_MIN_VERSION, '<=')) {
|
||||
$validator->fail(
|
||||
'MySQL version ' . self::MYSQL_MIN_VERSION . ' is the minimum supported version as of ' .
|
||||
self::MYSQL_MIN_VERSION_DATE . '. We recommend you update MySQL to a supported version (' .
|
||||
self::MYSQL_RECOMMENDED_VERSION . ' suggested). Failure to update MySQL will eventually cause issues.'
|
||||
self::MYSQL_MIN_VERSION_DATE . '. Update MySQL to a supported version (' .
|
||||
self::MYSQL_RECOMMENDED_VERSION . ' suggested).'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ class Database extends BaseValidation
|
|||
private function checkMode(Validator $validator)
|
||||
{
|
||||
// Test for lower case table name support
|
||||
$lc_mode = dbFetchCell('SELECT @@global.lower_case_table_names');
|
||||
$lc_mode = Eloquent::DB()->selectOne('SELECT @@global.lower_case_table_names as mode')->mode;
|
||||
if ($lc_mode != 0) {
|
||||
$validator->fail(
|
||||
'You have lower_case_table_names set to 1 or true in mysql config.',
|
||||
|
@ -144,7 +144,7 @@ class Database extends BaseValidation
|
|||
{
|
||||
$db = \config('database.connections.' . \config('database.default') . '.database');
|
||||
$query = "SELECT `TABLE_NAME` FROM information_schema.tables WHERE `TABLE_SCHEMA` = '$db' && `ENGINE` != 'InnoDB'";
|
||||
$tables = dbFetchRows($query);
|
||||
$tables = Eloquent::DB()->select($query);
|
||||
if (! empty($tables)) {
|
||||
$validator->result(
|
||||
ValidationResult::warn('Some tables are not using the recommended InnoDB engine, this may cause you issues.')
|
||||
|
@ -155,14 +155,14 @@ class Database extends BaseValidation
|
|||
|
||||
private function checkCollation(Validator $validator)
|
||||
{
|
||||
$db_name = dbFetchCell('SELECT DATABASE()');
|
||||
$db_name = Eloquent::DB()->selectOne('SELECT DATABASE() as name')->name;
|
||||
|
||||
// Test for correct character set and collation
|
||||
$db_collation_sql = "SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
|
||||
FROM information_schema.SCHEMATA S
|
||||
WHERE schema_name = '$db_name' AND
|
||||
( DEFAULT_CHARACTER_SET_NAME != 'utf8mb4' OR DEFAULT_COLLATION_NAME != 'utf8mb4_unicode_ci')";
|
||||
$collation = dbFetchRows($db_collation_sql);
|
||||
$collation = Eloquent::DB()->select($db_collation_sql);
|
||||
if (empty($collation) !== true) {
|
||||
$validator->fail(
|
||||
'MySQL Database collation is wrong: ' . implode(' ', $collation[0]),
|
||||
|
@ -174,7 +174,7 @@ class Database extends BaseValidation
|
|||
FROM information_schema.TABLES AS T, information_schema.COLLATION_CHARACTER_SET_APPLICABILITY AS C
|
||||
WHERE C.collation_name = T.table_collation AND T.table_schema = '$db_name' AND
|
||||
( C.CHARACTER_SET_NAME != 'utf8mb4' OR C.COLLATION_NAME != 'utf8mb4_unicode_ci' );";
|
||||
$collation_tables = dbFetchRows($table_collation_sql);
|
||||
$collation_tables = Eloquent::DB()->select($table_collation_sql);
|
||||
if (empty($collation_tables) !== true) {
|
||||
$result = ValidationResult::fail('MySQL tables collation is wrong: ')
|
||||
->setFix('Check https://community.librenms.org/t/new-default-database-charset-collation/14956 for info on how to fix.')
|
||||
|
@ -185,7 +185,7 @@ class Database extends BaseValidation
|
|||
$column_collation_sql = "SELECT TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
|
||||
FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '$db_name' AND
|
||||
( CHARACTER_SET_NAME != 'utf8mb4' OR COLLATION_NAME != 'utf8mb4_unicode_ci' );";
|
||||
$collation_columns = dbFetchRows($column_collation_sql);
|
||||
$collation_columns = Eloquent::DB()->select($column_collation_sql);
|
||||
if (empty($collation_columns) !== true) {
|
||||
$result = ValidationResult::fail('MySQL column collation is wrong: ')
|
||||
->setFix('Check https://community.librenms.org/t/new-default-database-charset-collation/14956 for info on how to fix.')
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
namespace LibreNMS\Validations;
|
||||
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Str;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Util\EnvHelper;
|
||||
|
@ -47,7 +48,7 @@ class User extends BaseValidation
|
|||
$lnms_groupname = \config('librenms.group');
|
||||
|
||||
if (! ($username === 'root' || $username === $lnms_username)) {
|
||||
if (isCli()) {
|
||||
if (App::runningInConsole()) {
|
||||
$validator->fail("You need to run this script as '$lnms_username' or root");
|
||||
} elseif (function_exists('posix_getgrnam')) {
|
||||
$lnms_group = posix_getgrnam($lnms_groupname);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
namespace LibreNMS;
|
||||
|
||||
use App;
|
||||
use Illuminate\Support\Str;
|
||||
use LibreNMS\Interfaces\ValidationGroup;
|
||||
use ReflectionClass;
|
||||
|
@ -73,14 +74,14 @@ class Validator
|
|||
}
|
||||
|
||||
if ((empty($validation_groups) && $group->isDefault()) || in_array($group_name, $validation_groups)) {
|
||||
if ($print_group_status && isCli()) {
|
||||
if ($print_group_status && App::runningInConsole()) {
|
||||
echo "Checking $group_name:";
|
||||
}
|
||||
|
||||
/** @var ValidationGroup $group */
|
||||
$group->validate($this);
|
||||
|
||||
if (isCli()) {
|
||||
if (App::runningInConsole()) {
|
||||
if ($print_group_status) {
|
||||
$status = ValidationResult::getStatusText($this->getGroupStatus($group_name));
|
||||
c_echo(" $status\n");
|
||||
|
|
|
@ -30,6 +30,8 @@ use Illuminate\Support\Arr;
|
|||
use LibreNMS\DB\Eloquent;
|
||||
use LibreNMS\DB\Schema;
|
||||
use LibreNMS\Interfaces\InstallerStep;
|
||||
use LibreNMS\ValidationResult;
|
||||
use LibreNMS\Validator;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
class DatabaseController extends InstallationController implements InstallerStep
|
||||
|
@ -66,17 +68,30 @@ class DatabaseController extends InstallationController implements InstallerStep
|
|||
session()->forget('install.database'); // reset db complete status
|
||||
|
||||
$ok = false;
|
||||
$message = '';
|
||||
$messages = [];
|
||||
try {
|
||||
$conn = Eloquent::DB('setup');
|
||||
$ok = $conn && ! is_null($conn->getPdo());
|
||||
|
||||
// validate Database
|
||||
$validator = new Validator();
|
||||
$validator->validate(['database']);
|
||||
$results = $validator->getResults('database');
|
||||
|
||||
/** @var \LibreNMS\ValidationResult $result */
|
||||
foreach ($results as $result) {
|
||||
if ($result->getStatus() == ValidationResult::FAILURE) {
|
||||
$ok = false;
|
||||
$messages[] = $result->getMessage();
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
$messages[] = $e->getMessage();
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'result' => $ok ? 'ok' : 'fail',
|
||||
'message' => $message,
|
||||
'message' => implode('<br />', $messages),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use LibreNMS\Config;
|
|||
$init_modules = ['nodb'];
|
||||
require __DIR__ . '/includes/init.php';
|
||||
|
||||
if (isCli()) {
|
||||
if (App::runningInConsole()) {
|
||||
// fill in db variables for legacy external scripts
|
||||
Config::populateLegacyDbCredentials();
|
||||
|
||||
|
|
|
@ -144,18 +144,9 @@ function shorthost($hostname, $len = 12)
|
|||
return $shorthost;
|
||||
}
|
||||
|
||||
function isCli()
|
||||
{
|
||||
if (php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR'])) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function print_error($text)
|
||||
{
|
||||
if (isCli()) {
|
||||
if (App::runningInConsole()) {
|
||||
c_echo('%r' . $text . "%n\n");
|
||||
} else {
|
||||
echo '<div class="alert alert-danger"><i class="fa fa-fw fa-exclamation-circle" aria-hidden="true"></i> ' . $text . '</div>';
|
||||
|
@ -164,7 +155,7 @@ function print_error($text)
|
|||
|
||||
function print_message($text)
|
||||
{
|
||||
if (isCli()) {
|
||||
if (App::runningInConsole()) {
|
||||
c_echo('%g' . $text . "%n\n");
|
||||
} else {
|
||||
echo '<div class="alert alert-success"><i class="fa fa-fw fa-check-circle" aria-hidden="true"></i> ' . $text . '</div>';
|
||||
|
@ -438,7 +429,7 @@ function c_echo($string, $enabled = true)
|
|||
return;
|
||||
}
|
||||
|
||||
if (isCli()) {
|
||||
if (App::runningInConsole()) {
|
||||
global $console_color;
|
||||
if ($console_color) {
|
||||
echo $console_color->convert($string);
|
||||
|
|
|
@ -279,7 +279,7 @@ function renamehost($id, $new, $source = 'console')
|
|||
|
||||
function device_discovery_trigger($id)
|
||||
{
|
||||
if (isCli() === false) {
|
||||
if (App::runningInConsole() === false) {
|
||||
ignore_user_abort(true);
|
||||
set_time_limit(0);
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ function device_discovery_trigger($id)
|
|||
|
||||
function delete_device($id)
|
||||
{
|
||||
if (isCli() === false) {
|
||||
if (App::runningInConsole() === false) {
|
||||
ignore_user_abort(true);
|
||||
set_time_limit(0);
|
||||
}
|
||||
|
@ -2017,27 +2017,6 @@ function get_schema_list()
|
|||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current database schema, will return 0 if there is no schema.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function get_db_schema()
|
||||
{
|
||||
try {
|
||||
$db = \LibreNMS\DB\Eloquent::DB();
|
||||
if ($db) {
|
||||
return (int) $db->table('dbSchema')
|
||||
->orderBy('version', 'DESC')
|
||||
->value('version');
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
// return default
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $device
|
||||
* @return int|null
|
||||
|
|
|
@ -41,7 +41,7 @@ if (config('cache.default') == 'database' && ! \Schema::hasTable('cache_locks'))
|
|||
|
||||
$schemaLock = Cache::lock('schema', 86000);
|
||||
if (! empty($skip_schema_lock) || $schemaLock->get()) {
|
||||
$db_rev = get_db_schema();
|
||||
$db_rev = \LibreNMS\DB\Schema::getLegacySchema();
|
||||
|
||||
$migrate_opts = ['--force' => true, '--ansi' => true];
|
||||
|
||||
|
@ -93,7 +93,7 @@ if (! empty($skip_schema_lock) || $schemaLock->get()) {
|
|||
|
||||
echo "-- Done\n";
|
||||
// end legacy update
|
||||
$db_rev = get_db_schema();
|
||||
$db_rev = \LibreNMS\DB\Schema::getLegacySchema();
|
||||
}
|
||||
|
||||
if ($db_rev == 1000) {
|
||||
|
|
|
@ -28,7 +28,7 @@ Debug::set(isset($options['d']));
|
|||
Datastore::init();
|
||||
|
||||
// Wait for schema update, as running during update can break update
|
||||
if (get_db_schema() < 107) {
|
||||
if (\LibreNMS\DB\Schema::getLegacySchema() < 107) {
|
||||
logfile('BILLING: Cannot continue until the database schema update to >= 107 is complete');
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -11,12 +11,13 @@ return [
|
|||
'database' => [
|
||||
'credentials' => 'Database Credentials',
|
||||
'host' => 'Host',
|
||||
'ip_empty' => 'Leave empty if using Host',
|
||||
'host_placeholder' => 'Use localhost for Unix-Socket',
|
||||
'name' => 'Database Name',
|
||||
'password' => 'Password',
|
||||
'port' => 'Port',
|
||||
'port_placeholder' => 'Leave empty if using Unix-Socket',
|
||||
'socket' => 'Unix-Socket',
|
||||
'socket_empty' => 'Leave empty if using Unix-Socket',
|
||||
'socket_placeholder' => 'Only use for custom socket path',
|
||||
'test' => 'Check Credentials',
|
||||
'title' => 'Configure Database',
|
||||
'username' => 'User',
|
||||
|
|
|
@ -28,19 +28,19 @@
|
|||
<div class="form-row pb-3">
|
||||
<label for="host" class="col-4 col-form-label text-right">@lang('install.database.host')</label>
|
||||
<div class="col-6">
|
||||
<input type="text" class="form-control" name="host" id="host" value="{{ $host ?? 'localhost' }}" placeholder="@lang('install.database.socket_empty')">
|
||||
<input type="text" class="form-control" name="host" id="host" value="{{ $host ?? 'localhost' }}" placeholder="@lang('install.database.host_placeholder')">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row pb-3">
|
||||
<label for="port" class="col-4 col-form-label text-right">@lang('install.database.port')</label>
|
||||
<div class="col-6">
|
||||
<input type="text" class="form-control" name="port" id="port" value="{{ $port ?? 3306 }}" placeholder="@lang('install.database.socket_empty')">
|
||||
<input type="text" class="form-control" name="port" id="port" value="{{ $port ?? 3306 }}" placeholder="@lang('install.database.port_placeholder')">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row pb-3">
|
||||
<label for="unix_socket" class="col-4 col-form-label text-right">@lang('install.database.socket')</label>
|
||||
<div class="col-6">
|
||||
<input type="text" class="form-control" name="unix_socket" id="unix_socket" value="{{ $unix_socket ?? '' }}" placeholder="@lang('install.database.ip_empty')">
|
||||
<input type="text" class="form-control" name="unix_socket" id="unix_socket" value="{{ $unix_socket ?? '' }}" placeholder="@lang('install.database.socket_placeholder')">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row pb-3">
|
||||
|
|
|
@ -68,7 +68,6 @@ if (! file_exists('vendor/autoload.php')) {
|
|||
require_once 'vendor/autoload.php';
|
||||
require_once 'includes/common.php';
|
||||
require_once 'includes/functions.php';
|
||||
require_once 'includes/dbFacile.php';
|
||||
|
||||
// Buffer output
|
||||
ob_start();
|
||||
|
|
Loading…
Reference in New Issue