Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14347669
D16902.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
D16902.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D16902: Run "DatabaseSetup" checks against all configured hosts
Attached
Detach File
Event Timeline
Log In to Comment