Page MenuHomePhabricator

D16902.id.diff
No OneTemporary

D16902.id.diff

diff --git a/src/aphront/configuration/AphrontApplicationConfiguration.php b/src/aphront/configuration/AphrontApplicationConfiguration.php
--- a/src/aphront/configuration/AphrontApplicationConfiguration.php
+++ b/src/aphront/configuration/AphrontApplicationConfiguration.php
@@ -89,7 +89,8 @@
if ($database_exception) {
$issue = PhabricatorSetupIssue::newDatabaseConnectionIssue(
- $database_exception);
+ $database_exception,
+ true);
$response = PhabricatorSetupCheck::newIssueResponse($issue);
return self::writeResponse($sink, $response);
}
diff --git a/src/applications/config/check/PhabricatorDatabaseSetupCheck.php b/src/applications/config/check/PhabricatorDatabaseSetupCheck.php
--- a/src/applications/config/check/PhabricatorDatabaseSetupCheck.php
+++ b/src/applications/config/check/PhabricatorDatabaseSetupCheck.php
@@ -43,38 +43,59 @@
$port));
}
- $masters = PhabricatorDatabaseRef::getMasterDatabaseRefs();
- if (!$masters) {
- // If we're implicitly in read-only mode during disaster recovery,
- // don't bother with these setup checks.
- return;
- }
+ $refs = PhabricatorDatabaseRef::getActiveDatabaseRefs();
+ $refs = mpull($refs, null, 'getRefKey');
+
+ // Test if we can connect to each database first. If we can not connect
+ // to a particular database, we only raise a warning: this allows new web
+ // nodes to start during a disaster, when some databases may be correctly
+ // configured but not reachable.
+
+ $connect_map = array();
+ $any_connection = false;
+ foreach ($refs as $ref_key => $ref) {
+ $conn_raw = $ref->newManagementConnection();
+
+ try {
+ queryfx($conn_raw, 'SELECT 1');
+ $database_exception = null;
+ $any_connection = true;
+ } catch (AphrontInvalidCredentialsQueryException $ex) {
+ $database_exception = $ex;
+ } catch (AphrontConnectionQueryException $ex) {
+ $database_exception = $ex;
+ }
- foreach ($masters as $master) {
- if ($this->checkMasterDatabase($master)) {
- break;
+ if ($database_exception) {
+ $connect_map[$ref_key] = $database_exception;
+ unset($refs[$ref_key]);
}
}
- }
- private function checkMasterDatabase(PhabricatorDatabaseRef $master) {
- $conn_raw = $master->newManagementConnection();
-
- try {
- queryfx($conn_raw, 'SELECT 1');
- $database_exception = null;
- } catch (AphrontInvalidCredentialsQueryException $ex) {
- $database_exception = $ex;
- } catch (AphrontConnectionQueryException $ex) {
- $database_exception = $ex;
+ if ($connect_map) {
+ // This is only a fatal error if we could not connect to anything. If
+ // possible, we still want to start if some database hosts can not be
+ // reached.
+ $is_fatal = !$any_connection;
+
+ foreach ($connect_map as $ref_key => $database_exception) {
+ $issue = PhabricatorSetupIssue::newDatabaseConnectionIssue(
+ $database_exception,
+ $is_fatal);
+ $this->addIssue($issue);
+ }
}
- if ($database_exception) {
- $issue = PhabricatorSetupIssue::newDatabaseConnectionIssue(
- $database_exception);
- $this->addIssue($issue);
- return true;
+ foreach ($refs as $ref_key => $ref) {
+ if ($this->executeRefChecks($ref)) {
+ return;
+ }
}
+ }
+
+ private function executeRefChecks(PhabricatorDatabaseRef $ref) {
+ $conn_raw = $ref->newManagementConnection();
+ $ref_key = $ref->getRefKey();
$engines = queryfx_all($conn_raw, 'SHOW ENGINES');
$engines = ipull($engines, 'Support', 'Engine');
@@ -82,17 +103,19 @@
$innodb = idx($engines, 'InnoDB');
if ($innodb != 'YES' && $innodb != 'DEFAULT') {
$message = pht(
- "The 'InnoDB' engine is not available in MySQL. Enable InnoDB in ".
- "your MySQL configuration.".
+ 'The "InnoDB" engine is not available in MySQL (on host "%s"). '.
+ 'Enable InnoDB in your MySQL configuration.'.
"\n\n".
- "(If you aleady created tables, MySQL incorrectly used some other ".
- "engine to create them. You need to convert them or drop and ".
- "reinitialize them.)");
+ '(If you aleady created tables, MySQL incorrectly used some other '.
+ 'engine to create them. You need to convert them or drop and '.
+ 'reinitialize them.)',
+ $ref_key);
$this->newIssue('mysql.innodb')
->setName(pht('MySQL InnoDB Engine Not Available'))
->setMessage($message)
->setIsFatal(true);
+
return true;
}
@@ -103,18 +126,20 @@
if (empty($databases[$namespace.'_meta_data'])) {
$message = pht(
- "Run the storage upgrade script to setup Phabricator's database ".
- "schema.");
+ 'Run the storage upgrade script to setup databases (host "%s" has '.
+ 'not been initialized).',
+ $ref_key);
$this->newIssue('storage.upgrade')
->setName(pht('Setup MySQL Schema'))
->setMessage($message)
->setIsFatal(true)
->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade'));
+
return true;
}
- $conn_meta = $master->newApplicationConnection(
+ $conn_meta = $ref->newApplicationConnection(
$namespace.'_meta_data');
$applied = queryfx_all($conn_meta, 'SELECT patch FROM patch_status');
@@ -124,15 +149,19 @@
$diff = array_diff_key($all, $applied);
if ($diff) {
+ $message = pht(
+ 'Run the storage upgrade script to upgrade databases (host "%s" is '.
+ 'out of date). Missing patches: %s.',
+ $ref_key,
+ implode(', ', array_keys($diff)));
+
$this->newIssue('storage.patch')
->setName(pht('Upgrade MySQL Schema'))
- ->setMessage(
- pht(
- "Run the storage upgrade script to upgrade Phabricator's ".
- "database schema. Missing patches:<br />%s<br />",
- phutil_implode_html(phutil_tag('br'), array_keys($diff))))
+ ->setIsFatal(true)
+ ->setMessage($message)
->addCommand(
hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade'));
+
return true;
}
}
diff --git a/src/applications/config/issue/PhabricatorSetupIssue.php b/src/applications/config/issue/PhabricatorSetupIssue.php
--- a/src/applications/config/issue/PhabricatorSetupIssue.php
+++ b/src/applications/config/issue/PhabricatorSetupIssue.php
@@ -21,7 +21,8 @@
private $links;
public static function newDatabaseConnectionIssue(
- AphrontQueryException $ex) {
+ AphrontQueryException $ex,
+ $is_fatal) {
$message = pht(
"Unable to connect to MySQL!\n\n".
@@ -29,15 +30,21 @@
"Make sure Phabricator and MySQL are correctly configured.",
$ex->getMessage());
- return id(new self())
+ $issue = id(new self())
->setIssueKey('mysql.connect')
->setName(pht('Can Not Connect to MySQL'))
->setMessage($message)
- ->setIsFatal(true)
+ ->setIsFatal($is_fatal)
->addRelatedPhabricatorConfig('mysql.host')
->addRelatedPhabricatorConfig('mysql.port')
->addRelatedPhabricatorConfig('mysql.user')
->addRelatedPhabricatorConfig('mysql.pass');
+
+ if (PhabricatorEnv::getEnvConfig('cluster.databases')) {
+ $issue->addRelatedPhabricatorConfig('cluster.databases');
+ }
+
+ return $issue;
}
public function addCommand($command) {
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php
@@ -23,8 +23,6 @@
public function didExecute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole();
- $api = $this->getSingleAPI();
-
if (!$this->isDryRun() && !$this->isForce()) {
$console->writeOut(
phutil_console_wrap(
@@ -44,46 +42,53 @@
}
}
- $patches = $this->getPatches();
+ $apis = $this->getMasterAPIs();
+ foreach ($apis as $api) {
+ $patches = $this->getPatches();
- if ($args->getArg('unittest-fixtures')) {
- $conn = $api->getConn(null);
- $databases = queryfx_all(
- $conn,
- 'SELECT DISTINCT(TABLE_SCHEMA) AS db '.
- 'FROM INFORMATION_SCHEMA.TABLES '.
- 'WHERE TABLE_SCHEMA LIKE %>',
- PhabricatorTestCase::NAMESPACE_PREFIX);
- $databases = ipull($databases, 'db');
- } else {
- $databases = $api->getDatabaseList($patches);
- $databases[] = $api->getDatabaseName('meta_data');
+ if ($args->getArg('unittest-fixtures')) {
+ $conn = $api->getConn(null);
+ $databases = queryfx_all(
+ $conn,
+ 'SELECT DISTINCT(TABLE_SCHEMA) AS db '.
+ 'FROM INFORMATION_SCHEMA.TABLES '.
+ 'WHERE TABLE_SCHEMA LIKE %>',
+ PhabricatorTestCase::NAMESPACE_PREFIX);
+ $databases = ipull($databases, 'db');
+ } else {
+ $databases = $api->getDatabaseList($patches);
+ $databases[] = $api->getDatabaseName('meta_data');
- // These are legacy databases that were dropped long ago. See T2237.
- $databases[] = $api->getDatabaseName('phid');
- $databases[] = $api->getDatabaseName('directory');
- }
+ // These are legacy databases that were dropped long ago. See T2237.
+ $databases[] = $api->getDatabaseName('phid');
+ $databases[] = $api->getDatabaseName('directory');
+ }
- foreach ($databases as $database) {
- if ($this->isDryRun()) {
- $console->writeOut(
- "%s\n",
- pht("DRYRUN: Would drop database '%s'.", $database));
- } else {
+ foreach ($databases as $database) {
+ if ($this->isDryRun()) {
+ $console->writeOut(
+ "%s\n",
+ pht("DRYRUN: Would drop database '%s'.", $database));
+ } else {
+ $console->writeOut(
+ "%s\n",
+ pht("Dropping database '%s'...", $database));
+ queryfx(
+ $api->getConn(null),
+ 'DROP DATABASE IF EXISTS %T',
+ $database);
+ }
+ }
+
+ if (!$this->isDryRun()) {
$console->writeOut(
"%s\n",
- pht("Dropping database '%s'...", $database));
- queryfx(
- $api->getConn(null),
- 'DROP DATABASE IF EXISTS %T',
- $database);
+ pht(
+ 'Storage on "%s" was destroyed.',
+ $api->getRef()->getRefKey()));
}
}
- if (!$this->isDryRun()) {
- $console->writeOut("%s\n", pht('Storage was destroyed.'));
- }
-
return 0;
}

File Metadata

Mime Type
text/plain
Expires
Fri, Dec 20, 3:05 AM (19 h, 5 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6909331
Default Alt Text
D16902.id.diff (10 KB)

Event Timeline