Changeset View
Changeset View
Standalone View
Standalone View
src/applications/config/check/PhabricatorDatabaseSetupCheck.php
| <?php | <?php | ||||
| final class PhabricatorDatabaseSetupCheck extends PhabricatorSetupCheck { | final class PhabricatorDatabaseSetupCheck extends PhabricatorSetupCheck { | ||||
| public function getDefaultGroup() { | public function getDefaultGroup() { | ||||
| return self::GROUP_IMPORTANT; | return self::GROUP_IMPORTANT; | ||||
| } | } | ||||
| public function getExecutionOrder() { | public function getExecutionOrder() { | ||||
| // This must run after basic PHP checks, but before most other checks. | // This must run after basic PHP checks, but before most other checks. | ||||
| return 500; | return 500; | ||||
| } | } | ||||
| protected function executeChecks() { | protected function executeChecks() { | ||||
| $master = PhabricatorDatabaseRef::getMasterDatabaseRef(); | $host = PhabricatorEnv::getEnvConfig('mysql.host'); | ||||
| if (!$master) { | $matches = null; | ||||
| if (preg_match('/^([^:]+):(\d+)$/', $host, $matches)) { | |||||
| $host = $matches[1]; | |||||
| $port = $matches[2]; | |||||
| $this->newIssue('storage.mysql.hostport') | |||||
| ->setName(pht('Deprecated mysql.host Format')) | |||||
| ->setSummary( | |||||
| pht( | |||||
| 'Move port information from `%s` to `%s` in your config.', | |||||
| 'mysql.host', | |||||
| 'mysql.port')) | |||||
| ->setMessage( | |||||
| pht( | |||||
| 'Your `%s` configuration contains a port number, but this usage '. | |||||
| 'is deprecated. Instead, put the port number in `%s`.', | |||||
| 'mysql.host', | |||||
| 'mysql.port')) | |||||
| ->addPhabricatorConfig('mysql.host') | |||||
| ->addPhabricatorConfig('mysql.port') | |||||
| ->addCommand( | |||||
| hsprintf( | |||||
| '<tt>phabricator/ $</tt> ./bin/config set mysql.host %s', | |||||
| $host)) | |||||
| ->addCommand( | |||||
| hsprintf( | |||||
| '<tt>phabricator/ $</tt> ./bin/config set mysql.port %s', | |||||
| $port)); | |||||
| } | |||||
| $masters = PhabricatorDatabaseRef::getMasterDatabaseRefs(); | |||||
| if (!$masters) { | |||||
| // If we're implicitly in read-only mode during disaster recovery, | // If we're implicitly in read-only mode during disaster recovery, | ||||
| // don't bother with these setup checks. | // don't bother with these setup checks. | ||||
| return; | return; | ||||
| } | } | ||||
| foreach ($masters as $master) { | |||||
| if ($this->checkMasterDatabase($master)) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| private function checkMasterDatabase(PhabricatorDatabaseRef $master) { | |||||
| $conn_raw = $master->newManagementConnection(); | $conn_raw = $master->newManagementConnection(); | ||||
| try { | try { | ||||
| queryfx($conn_raw, 'SELECT 1'); | queryfx($conn_raw, 'SELECT 1'); | ||||
| $database_exception = null; | $database_exception = null; | ||||
| } catch (AphrontInvalidCredentialsQueryException $ex) { | } catch (AphrontInvalidCredentialsQueryException $ex) { | ||||
| $database_exception = $ex; | $database_exception = $ex; | ||||
| } catch (AphrontConnectionQueryException $ex) { | } catch (AphrontConnectionQueryException $ex) { | ||||
| $database_exception = $ex; | $database_exception = $ex; | ||||
| } | } | ||||
| if ($database_exception) { | if ($database_exception) { | ||||
| $issue = PhabricatorSetupIssue::newDatabaseConnectionIssue( | $issue = PhabricatorSetupIssue::newDatabaseConnectionIssue( | ||||
| $database_exception); | $database_exception); | ||||
| $this->addIssue($issue); | $this->addIssue($issue); | ||||
| return; | return true; | ||||
| } | } | ||||
| $engines = queryfx_all($conn_raw, 'SHOW ENGINES'); | $engines = queryfx_all($conn_raw, 'SHOW ENGINES'); | ||||
| $engines = ipull($engines, 'Support', 'Engine'); | $engines = ipull($engines, 'Support', 'Engine'); | ||||
| $innodb = idx($engines, 'InnoDB'); | $innodb = idx($engines, 'InnoDB'); | ||||
| if ($innodb != 'YES' && $innodb != 'DEFAULT') { | if ($innodb != 'YES' && $innodb != 'DEFAULT') { | ||||
| $message = pht( | $message = pht( | ||||
| "The 'InnoDB' engine is not available in MySQL. Enable InnoDB in ". | "The 'InnoDB' engine is not available in MySQL. Enable InnoDB in ". | ||||
| "your MySQL configuration.". | "your MySQL configuration.". | ||||
| "\n\n". | "\n\n". | ||||
| "(If you aleady created tables, MySQL incorrectly used some other ". | "(If you aleady created tables, MySQL incorrectly used some other ". | ||||
| "engine to create them. You need to convert them or drop and ". | "engine to create them. You need to convert them or drop and ". | ||||
| "reinitialize them.)"); | "reinitialize them.)"); | ||||
| $this->newIssue('mysql.innodb') | $this->newIssue('mysql.innodb') | ||||
| ->setName(pht('MySQL InnoDB Engine Not Available')) | ->setName(pht('MySQL InnoDB Engine Not Available')) | ||||
| ->setMessage($message) | ->setMessage($message) | ||||
| ->setIsFatal(true); | ->setIsFatal(true); | ||||
| return; | return true; | ||||
| } | } | ||||
| $namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace'); | $namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace'); | ||||
| $databases = queryfx_all($conn_raw, 'SHOW DATABASES'); | $databases = queryfx_all($conn_raw, 'SHOW DATABASES'); | ||||
| $databases = ipull($databases, 'Database', 'Database'); | $databases = ipull($databases, 'Database', 'Database'); | ||||
| if (empty($databases[$namespace.'_meta_data'])) { | if (empty($databases[$namespace.'_meta_data'])) { | ||||
| $message = pht( | $message = pht( | ||||
| "Run the storage upgrade script to setup Phabricator's database ". | "Run the storage upgrade script to setup Phabricator's database ". | ||||
| "schema."); | "schema."); | ||||
| $this->newIssue('storage.upgrade') | $this->newIssue('storage.upgrade') | ||||
| ->setName(pht('Setup MySQL Schema')) | ->setName(pht('Setup MySQL Schema')) | ||||
| ->setMessage($message) | ->setMessage($message) | ||||
| ->setIsFatal(true) | ->setIsFatal(true) | ||||
| ->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade')); | ->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade')); | ||||
| } else { | return true; | ||||
| } | |||||
| $conn_meta = $master->newApplicationConnection( | $conn_meta = $master->newApplicationConnection( | ||||
| $namespace.'_meta_data'); | $namespace.'_meta_data'); | ||||
| $applied = queryfx_all($conn_meta, 'SELECT patch FROM patch_status'); | $applied = queryfx_all($conn_meta, 'SELECT patch FROM patch_status'); | ||||
| $applied = ipull($applied, 'patch', 'patch'); | $applied = ipull($applied, 'patch', 'patch'); | ||||
| $all = PhabricatorSQLPatchList::buildAllPatches(); | $all = PhabricatorSQLPatchList::buildAllPatches(); | ||||
| $diff = array_diff_key($all, $applied); | $diff = array_diff_key($all, $applied); | ||||
| if ($diff) { | if ($diff) { | ||||
| $this->newIssue('storage.patch') | $this->newIssue('storage.patch') | ||||
| ->setName(pht('Upgrade MySQL Schema')) | ->setName(pht('Upgrade MySQL Schema')) | ||||
| ->setMessage( | ->setMessage( | ||||
| pht( | pht( | ||||
| "Run the storage upgrade script to upgrade Phabricator's ". | "Run the storage upgrade script to upgrade Phabricator's ". | ||||
| "database schema. Missing patches:<br />%s<br />", | "database schema. Missing patches:<br />%s<br />", | ||||
| phutil_implode_html(phutil_tag('br'), array_keys($diff)))) | phutil_implode_html(phutil_tag('br'), array_keys($diff)))) | ||||
| ->addCommand( | ->addCommand( | ||||
| hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade')); | hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade')); | ||||
| return true; | |||||
| } | } | ||||
| } | } | ||||
| $host = PhabricatorEnv::getEnvConfig('mysql.host'); | |||||
| $matches = null; | |||||
| if (preg_match('/^([^:]+):(\d+)$/', $host, $matches)) { | |||||
| $host = $matches[1]; | |||||
| $port = $matches[2]; | |||||
| $this->newIssue('storage.mysql.hostport') | |||||
| ->setName(pht('Deprecated mysql.host Format')) | |||||
| ->setSummary( | |||||
| pht( | |||||
| 'Move port information from `%s` to `%s` in your config.', | |||||
| 'mysql.host', | |||||
| 'mysql.port')) | |||||
| ->setMessage( | |||||
| pht( | |||||
| 'Your `%s` configuration contains a port number, but this usage '. | |||||
| 'is deprecated. Instead, put the port number in `%s`.', | |||||
| 'mysql.host', | |||||
| 'mysql.port')) | |||||
| ->addPhabricatorConfig('mysql.host') | |||||
| ->addPhabricatorConfig('mysql.port') | |||||
| ->addCommand( | |||||
| hsprintf( | |||||
| '<tt>phabricator/ $</tt> ./bin/config set mysql.host %s', | |||||
| $host)) | |||||
| ->addCommand( | |||||
| hsprintf( | |||||
| '<tt>phabricator/ $</tt> ./bin/config set mysql.port %s', | |||||
| $port)); | |||||
| } | |||||
| } | |||||
| } | } | ||||