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)); | |||||
} | |||||
} | |||||
} | } |