diff --git a/modules/monitoring/application/forms/Setup/IdoResourcePage.php b/modules/monitoring/application/forms/Setup/IdoResourcePage.php index 2bb4de3a9..3e23d5125 100644 --- a/modules/monitoring/application/forms/Setup/IdoResourcePage.php +++ b/modules/monitoring/application/forms/Setup/IdoResourcePage.php @@ -8,6 +8,7 @@ use Icinga\Forms\Config\ResourceConfigForm; use Icinga\Forms\Config\Resource\DbResourceForm; use Icinga\Web\Form; use Icinga\Module\Monitoring\Forms\Config\BackendConfigForm; +use Icinga\Module\Setup\Utils\DbTool; class IdoResourcePage extends Form { @@ -73,23 +74,8 @@ class IdoResourcePage extends Form } if (! isset($formData['skip_validation']) || !$formData['skip_validation']) { - $inspection = ResourceConfigForm::inspectResource($this); - if ($inspection !== null && $inspection->hasError()) { - $this->error($inspection->getError()); - $this->addSkipValidationCheckbox($this->translate( - 'Check this to not to validate connectivity with the given database server.' - )); - return false; - } - - $configObject = new ConfigObject($this->getValues()); - if ( - ! BackendConfigForm::isValidIdoSchema($this, $configObject) - || !BackendConfigForm::isValidIdoInstance($this, $configObject) - ) { - $this->addSkipValidationCheckbox($this->translate( - 'Check this to not to validate the IDO schema in the given database.' - )); + if (! $this->validateConfiguration()) { + $this->addSkipValidationCheckbox(); return false; } } @@ -109,8 +95,31 @@ class IdoResourcePage extends Form public function isValidPartial(array $formData) { if (isset($formData['backend_validation']) && parent::isValid($formData)) { - $inspection = ResourceConfigForm::inspectResource($this); - if ($inspection !== null) { + if (! $this->validateConfiguration(true)) { + return false; + } + + $this->info($this->translate('The configuration has been successfully validated.')); + } elseif (! isset($formData['backend_validation'])) { + // This is usually done by isValid(Partial), but as we're not calling any of these... + $this->populate($formData); + } + + return true; + } + + /** + * Return whether the configuration is valid + * + * @param bool $showLog Whether to show the validation log + * + * @return bool + */ + protected function validateConfiguration($showLog = false) + { + $inspection = ResourceConfigForm::inspectResource($this); + if ($inspection !== null) { + if ($showLog) { $join = function ($e) use (& $join) { return is_string($e) ? $e : join("\n", array_map($join, $e)); }; @@ -127,45 +136,53 @@ class IdoResourcePage extends Form ) ) ); - - if ($inspection->hasError()) { - $this->warning(sprintf( - $this->translate('Failed to successfully validate the configuration: %s'), - $inspection->getError() - )); - return false; - } } - $this->info($this->translate('The configuration has been successfully validated.')); - } elseif (! isset($formData['backend_validation'])) { - // This is usually done by isValid(Partial), but as we're not calling any of these... - $this->populate($formData); + if ($inspection->hasError()) { + $this->error(sprintf( + $this->translate('Failed to successfully validate the configuration: %s'), + $inspection->getError() + )); + return false; + } + } + + $configObject = new ConfigObject($this->getValues()); + if ( + ! BackendConfigForm::isValidIdoSchema($this, $configObject) + || !BackendConfigForm::isValidIdoInstance($this, $configObject) + ) { + return false; + } + + if ($this->getValue('db') === 'pgsql') { + $db = new DbTool($this->getValues()); + $version = $db->connectToDb()->getServerVersion(); + if (version_compare($version, '9.1', '<')) { + $this->error($this->translate(sprintf( + 'The server\'s version %s is too old. The minimum required version is %s.', + $version, + '9.1' + ))); + return false; + } } return true; } /** - * Add a checkbox to the form by which the user can skip the resource validation - * - * @param string $description + * Add a checkbox to the form by which the user can skip the configuration validation */ - protected function addSkipValidationCheckbox($description = null) + protected function addSkipValidationCheckbox() { - if (empty($description)) { - $description = $this->translate( - 'Proceed without any further (custom) validation.' - ); - } - $this->addElement( 'checkbox', 'skip_validation', array( 'required' => true, 'label' => $this->translate('Skip Validation'), - 'description' => $description + 'description' => $this->translate('Check this to not to validate the configuration') ) ); } diff --git a/modules/setup/application/controllers/IndexController.php b/modules/setup/application/controllers/IndexController.php index eec43a737..4685d9841 100644 --- a/modules/setup/application/controllers/IndexController.php +++ b/modules/setup/application/controllers/IndexController.php @@ -15,6 +15,11 @@ class Setup_IndexController extends Controller */ protected $requiresAuthentication = false; + /** + * {@inheritdoc} + */ + protected $innerLayout = 'inline'; + /** * Show the web wizard and run the configuration once finished */ diff --git a/modules/setup/application/forms/DbResourcePage.php b/modules/setup/application/forms/DbResourcePage.php index 6da2d03fc..22b0576d6 100644 --- a/modules/setup/application/forms/DbResourcePage.php +++ b/modules/setup/application/forms/DbResourcePage.php @@ -68,11 +68,7 @@ class DbResourcePage extends Form } if (false === isset($data['skip_validation']) || $data['skip_validation'] == 0) { - try { - $db = new DbTool($this->getValues()); - $db->checkConnectivity(); - } catch (PDOException $e) { - $this->error($e->getMessage()); + if (! $this->validateConfiguration()) { $this->addSkipValidationCheckbox(); return false; } @@ -93,14 +89,7 @@ class DbResourcePage extends Form public function isValidPartial(array $formData) { if (isset($formData['backend_validation']) && parent::isValid($formData)) { - try { - $db = new DbTool($this->getValues()); - $db->checkConnectivity(); - } catch (PDOException $e) { - $this->warning(sprintf( - $this->translate('Failed to successfully validate the configuration: %s'), - $e->getMessage() - )); + if (! $this->validateConfiguration()) { return false; } @@ -114,7 +103,55 @@ class DbResourcePage extends Form } /** - * Add a checkbox to the form by which the user can skip the connection validation + * Return whether the configuration is valid + * + * @return bool + */ + protected function validateConfiguration() + { + try { + $db = new DbTool($this->getValues()); + $db->checkConnectivity(); + } catch (PDOException $e) { + $this->error(sprintf( + $this->translate('Failed to successfully validate the configuration: %s'), + $e->getMessage() + )); + return false; + } + + if ($this->getValue('db') === 'pgsql') { + if (! $db->isConnected()) { + try { + $db->connectToDb(); + } catch (PDOException $e) { + $this->warning($this->translate(sprintf( + 'Unable to check the server\'s version. This is usually not a critical error as there is' + . ' probably only access to the database permitted which does not exist yet. If you are' + . ' absolutely sure you are running PostgreSQL in a version equal to or newer than 9.1,' + . ' you can skip the validation and safely proceed to the next step. The error was: %s', + $e->getMessage() + ))); + return false; + } + } + + $version = $db->getServerVersion(); + if (version_compare($version, '9.1', '<')) { + $this->error($this->translate(sprintf( + 'The server\'s version %s is too old. The minimum required version is %s.', + $version, + '9.1' + ))); + return false; + } + } + + return true; + } + + /** + * Add a checkbox to the form by which the user can skip the configuration validation */ protected function addSkipValidationCheckbox() { @@ -124,9 +161,7 @@ class DbResourcePage extends Form array( 'required' => true, 'label' => $this->translate('Skip Validation'), - 'description' => $this->translate( - 'Check this to not to validate connectivity with the given database server' - ) + 'description' => $this->translate('Check this to not to validate the configuration') ) ); } diff --git a/modules/setup/library/Setup/Utils/DbTool.php b/modules/setup/library/Setup/Utils/DbTool.php index bf3465458..03f10ebf4 100644 --- a/modules/setup/library/Setup/Utils/DbTool.php +++ b/modules/setup/library/Setup/Utils/DbTool.php @@ -204,6 +204,16 @@ class DbTool } } + /** + * Return whether a connection with the server has been established + * + * @return bool + */ + public function isConnected() + { + return $this->pdoConn !== null; + } + /** * Establish a connection with the database or just the server by omitting the database name * @@ -434,6 +444,24 @@ class DbTool return $stmt; } + /** + * Return the version of the server currently connected to + * + * @return string|null + */ + public function getServerVersion() + { + if ($this->config['db'] === 'mysql') { + return $this->query('show variables like "version"')->fetchColumn(1) ?: null; + } elseif ($this->config['db'] === 'pgsql') { + return $this->query('show server_version')->fetchColumn() ?: null; + } else { + throw new LogicException( + sprintf('Unable to fetch the server\'s version. Unsupported PDO driver "%s"', $this->config['db']) + ); + } + } + /** * Import the given SQL file *