Page MenuHomePhabricator

D16848.id40570.diff
No OneTemporary

D16848.id40570.diff

diff --git a/scripts/sql/manage_storage.php b/scripts/sql/manage_storage.php
--- a/scripts/sql/manage_storage.php
+++ b/scripts/sql/manage_storage.php
@@ -34,7 +34,13 @@
'name' => 'host',
'param' => 'hostname',
'help' => pht(
- 'Connect to __host__ instead of the default host.'),
+ 'Operate on the database server identified by __hostname__.'),
+ ),
+ array(
+ 'name' => 'ref',
+ 'param' => 'ref',
+ 'help' => pht(
+ 'Operate on the database identified by __ref__.'),
),
array(
'name' => 'user',
@@ -81,120 +87,147 @@
// First, test that the Phabricator configuration is set up correctly. After
// we know this works we'll test any administrative credentials specifically.
-$host = $args->getArg('host');
-if (strlen($host)) {
- $ref = null;
-
- $refs = PhabricatorDatabaseRef::getLiveRefs();
+$refs = PhabricatorDatabaseRef::getActiveDatabaseRefs();
+if (!$refs) {
+ throw new PhutilArgumentUsageException(
+ pht('No databases are configured.'));
+}
- // Include the master in case the user is just specifying a redundant
- // "--host" flag for no reason and does not actually have a database
- // cluster configured.
- foreach (PhabricatorDatabaseRef::getMasterDatabaseRefs() as $master_ref) {
- $refs[] = $master_ref;
+$host = $args->getArg('host');
+$ref_key = $args->getArg('ref');
+if (strlen($host) || strlen($ref_key)) {
+ if ($host && $ref_key) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Use "--host" or "--ref" to select a database, but not both.'));
}
+ $refs = PhabricatorDatabaseRef::getActiveDatabaseRefs();
+
+ $possible_refs = array();
foreach ($refs as $possible_ref) {
- if ($possible_ref->getHost() == $host) {
- $ref = $possible_ref;
+ if ($host && ($possible_ref->getHost() == $host)) {
+ $possible_refs[] = $possible_ref;
+ break;
+ }
+ if ($ref_key && ($possible_ref->getRefKey() == $ref_key)) {
+ $possible_refs[] = $possible_ref;
break;
}
}
- if (!$ref) {
+ if (!$possible_refs) {
+ if ($host) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'There is no configured database on host "%s". This command can '.
+ 'only interact with configured databases.',
+ $host));
+ } else {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'There is no configured database with ref "%s". This command can '.
+ 'only interact with configured databases.',
+ $ref_key));
+ }
+ }
+
+ if (count($possible_refs) > 1) {
throw new PhutilArgumentUsageException(
pht(
- 'There is no configured database on host "%s". This command can '.
- 'only interact with configured databases.',
+ 'Host "%s" identifies more than one database. Use "--ref" to select '.
+ 'a specific database.',
$host));
}
-} else {
- $ref = PhabricatorDatabaseRef::getMasterDatabaseRef();
- if (!$ref) {
- throw new Exception(
- pht('No database master is configured.'));
- }
-}
-
-$default_user = $ref->getUser();
-$default_host = $ref->getHost();
-$default_port = $ref->getPort();
-$test_api = id(new PhabricatorStorageManagementAPI())
- ->setUser($default_user)
- ->setHost($default_host)
- ->setPort($default_port)
- ->setPassword($ref->getPass())
- ->setNamespace($args->getArg('namespace'));
-
-try {
- queryfx(
- $test_api->getConn(null),
- 'SELECT 1');
-} catch (AphrontQueryException $ex) {
- $message = phutil_console_format(
- "**%s**\n\n%s\n\n%s\n\n%s\n\n**%s**: %s\n",
- pht('MySQL Credentials Not Configured'),
- pht(
- 'Unable to connect to MySQL using the configured credentials. '.
- 'You must configure standard credentials before you can upgrade '.
- 'storage. Run these commands to set up credentials:'),
- " phabricator/ $ ./bin/config set mysql.host __host__\n".
- " phabricator/ $ ./bin/config set mysql.user __username__\n".
- " phabricator/ $ ./bin/config set mysql.pass __password__",
- pht(
- 'These standard credentials are separate from any administrative '.
- 'credentials provided to this command with __%s__ or '.
- '__%s__, and must be configured correctly before you can proceed.',
- '--user',
- '--password'),
- pht('Raw MySQL Error'),
- $ex->getMessage());
- echo phutil_console_wrap($message);
- exit(1);
+ $refs = $possible_refs;
}
-if ($args->getArg('password') === null) {
- // This is already a PhutilOpaqueEnvelope.
- $password = $ref->getPass();
-} else {
- // Put this in a PhutilOpaqueEnvelope.
- $password = new PhutilOpaqueEnvelope($args->getArg('password'));
- PhabricatorEnv::overrideConfig('mysql.pass', $args->getArg('password'));
-}
+$apis = array();
+foreach ($refs as $ref) {
+ $default_user = $ref->getUser();
+ $default_host = $ref->getHost();
+ $default_port = $ref->getPort();
+
+ $test_api = id(new PhabricatorStorageManagementAPI())
+ ->setUser($default_user)
+ ->setHost($default_host)
+ ->setPort($default_port)
+ ->setPassword($ref->getPass())
+ ->setNamespace($args->getArg('namespace'));
+
+ try {
+ queryfx(
+ $test_api->getConn(null),
+ 'SELECT 1');
+ } catch (AphrontQueryException $ex) {
+ $message = phutil_console_format(
+ "**%s**\n\n%s\n\n%s\n\n%s\n\n**%s**: %s\n",
+ pht('MySQL Credentials Not Configured'),
+ pht(
+ 'Unable to connect to MySQL using the configured credentials. '.
+ 'You must configure standard credentials before you can upgrade '.
+ 'storage. Run these commands to set up credentials:'),
+ " phabricator/ $ ./bin/config set mysql.host __host__\n".
+ " phabricator/ $ ./bin/config set mysql.user __username__\n".
+ " phabricator/ $ ./bin/config set mysql.pass __password__",
+ pht(
+ 'These standard credentials are separate from any administrative '.
+ 'credentials provided to this command with __%s__ or '.
+ '__%s__, and must be configured correctly before you can proceed.',
+ '--user',
+ '--password'),
+ pht('Raw MySQL Error'),
+ $ex->getMessage());
+ echo phutil_console_wrap($message);
+ exit(1);
+ }
-$selected_user = $args->getArg('user');
-if ($selected_user === null) {
- $selected_user = $default_user;
-}
+ if ($args->getArg('password') === null) {
+ // This is already a PhutilOpaqueEnvelope.
+ $password = $ref->getPass();
+ } else {
+ // Put this in a PhutilOpaqueEnvelope.
+ $password = new PhutilOpaqueEnvelope($args->getArg('password'));
+ PhabricatorEnv::overrideConfig('mysql.pass', $args->getArg('password'));
+ }
-$api = id(new PhabricatorStorageManagementAPI())
- ->setUser($selected_user)
- ->setHost($default_host)
- ->setPort($default_port)
- ->setPassword($password)
- ->setNamespace($args->getArg('namespace'))
- ->setDisableUTF8MB4($args->getArg('disable-utf8mb4'));
-PhabricatorEnv::overrideConfig('mysql.user', $api->getUser());
+ $selected_user = $args->getArg('user');
+ if ($selected_user === null) {
+ $selected_user = $default_user;
+ }
-try {
- queryfx(
- $api->getConn(null),
- 'SELECT 1');
-} catch (AphrontQueryException $ex) {
- $message = phutil_console_format(
- "**%s**\n\n%s\n\n**%s**: %s\n",
- pht('Bad Administrative Credentials'),
- pht(
- 'Unable to connect to MySQL using the administrative credentials '.
- 'provided with the __%s__ and __%s__ flags. Check that '.
- 'you have entered them correctly.',
- '--user',
- '--password'),
- pht('Raw MySQL Error'),
- $ex->getMessage());
- echo phutil_console_wrap($message);
- exit(1);
+ $api = id(new PhabricatorStorageManagementAPI())
+ ->setUser($selected_user)
+ ->setHost($default_host)
+ ->setPort($default_port)
+ ->setPassword($password)
+ ->setNamespace($args->getArg('namespace'))
+ ->setDisableUTF8MB4($args->getArg('disable-utf8mb4'));
+ PhabricatorEnv::overrideConfig('mysql.user', $api->getUser());
+
+ try {
+ queryfx(
+ $api->getConn(null),
+ 'SELECT 1');
+ } catch (AphrontQueryException $ex) {
+ $message = phutil_console_format(
+ "**%s**\n\n%s\n\n**%s**: %s\n",
+ pht('Bad Administrative Credentials'),
+ pht(
+ 'Unable to connect to MySQL using the administrative credentials '.
+ 'provided with the __%s__ and __%s__ flags. Check that '.
+ 'you have entered them correctly.',
+ '--user',
+ '--password'),
+ pht('Raw MySQL Error'),
+ $ex->getMessage());
+ echo phutil_console_wrap($message);
+ exit(1);
+ }
+
+ $api->setRef($ref);
+ $apis[] = $api;
}
$workflows = id(new PhutilClassMapQuery())
@@ -204,7 +237,7 @@
$patches = PhabricatorSQLPatchList::buildAllPatches();
foreach ($workflows as $workflow) {
- $workflow->setAPI($api);
+ $workflow->setAPIs($apis);
$workflow->setPatches($patches);
}
diff --git a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
--- a/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
+++ b/src/applications/config/schema/PhabricatorConfigSchemaQuery.php
@@ -2,6 +2,30 @@
final class PhabricatorConfigSchemaQuery extends Phobject {
+ private $refs;
+ private $apis;
+
+ public function setRefs(array $refs) {
+ $this->refs = $refs;
+ return $this;
+ }
+
+ public function getRefs() {
+ if (!$this->refs) {
+ return PhabricatorDatabaseRef::getMasterDatabaseRefs();
+ }
+ return $this->refs;
+ }
+
+ public function setAPIs(array $apis) {
+ $map = array();
+ foreach ($apis as $api) {
+ $map[$api->getRef()->getRefKey()] = $api;
+ }
+ $this->apis = $map;
+ return $this;
+ }
+
private function getDatabaseNames(PhabricatorDatabaseRef $ref) {
$api = $this->getAPI($ref);
$patches = PhabricatorSQLPatchList::buildAllPatches();
@@ -11,6 +35,12 @@
}
private function getAPI(PhabricatorDatabaseRef $ref) {
+ $key = $ref->getRefKey();
+
+ if (isset($this->apis[$key])) {
+ return $this->apis[$key];
+ }
+
return id(new PhabricatorStorageManagementAPI())
->setUser($ref->getUser())
->setHost($ref->getHost())
@@ -20,7 +50,7 @@
}
public function loadActualSchemata() {
- $refs = PhabricatorDatabaseRef::getMasterDatabaseRefs();
+ $refs = $this->getRefs();
$schemata = array();
foreach ($refs as $ref) {
@@ -183,7 +213,7 @@
}
public function loadExpectedSchemata() {
- $refs = PhabricatorDatabaseRef::getMasterDatabaseRefs();
+ $refs = $this->getRefs();
$schemata = array();
foreach ($refs as $ref) {
diff --git a/src/infrastructure/cluster/PhabricatorDatabaseRef.php b/src/infrastructure/cluster/PhabricatorDatabaseRef.php
--- a/src/infrastructure/cluster/PhabricatorDatabaseRef.php
+++ b/src/infrastructure/cluster/PhabricatorDatabaseRef.php
@@ -223,7 +223,7 @@
);
}
- public static function getLiveRefs() {
+ public static function getClusterRefs() {
$cache = PhabricatorCaches::getRequestCache();
$refs = $cache->getKey(self::KEY_REFS);
@@ -457,8 +457,22 @@
return $this->healthRecord;
}
+ public static function getActiveDatabaseRefs() {
+ $refs = array();
+
+ foreach (self::getMasterDatabaseRefs() as $ref) {
+ $refs[] = $ref;
+ }
+
+ foreach (self::getReplicaDatabaseRefs() as $ref) {
+ $refs[] = $ref;
+ }
+
+ return $refs;
+ }
+
public static function getMasterDatabaseRefs() {
- $refs = self::getLiveRefs();
+ $refs = self::getClusterRefs();
if (!$refs) {
return array(self::getLiveIndividualRef());
@@ -477,13 +491,6 @@
return $masters;
}
- public static function getMasterDatabaseRef() {
- // TODO: Remove this method; it no longer makes sense with application
- // partitioning.
-
- return head(self::getMasterDatabaseRefs());
- }
-
public static function getMasterDatabaseRefForDatabase($database) {
$masters = self::getMasterDatabaseRefs();
@@ -507,7 +514,7 @@
}
public static function getReplicaDatabaseRefs() {
- $refs = self::getLiveRefs();
+ $refs = self::getClusterRefs();
if (!$refs) {
return array();
diff --git a/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php b/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php
--- a/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php
+++ b/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php
@@ -2,6 +2,7 @@
final class PhabricatorStorageManagementAPI extends Phobject {
+ private $ref;
private $host;
private $user;
private $port;
@@ -74,6 +75,15 @@
return $this->port;
}
+ public function setRef(PhabricatorDatabaseRef $ref) {
+ $this->ref = $ref;
+ return $this;
+ }
+
+ public function getRef() {
+ return $this->ref;
+ }
+
public function getDatabaseName($fragment) {
return $this->namespace.'_'.$fragment;
}
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php
@@ -27,12 +27,19 @@
public function didExecute(PhutilArgumentParser $args) {
$unsafe = $args->getArg('unsafe');
- $this->requireAllPatchesApplied();
- return $this->adjustSchemata($unsafe);
+ foreach ($this->getMasterAPIs() as $api) {
+ $this->requireAllPatchesApplied($api);
+ $err = $this->adjustSchemata($api, $unsafe);
+ if ($err) {
+ return $err;
+ }
+ }
+
+ return 0;
}
- private function requireAllPatchesApplied() {
- $api = $this->getAPI();
+ private function requireAllPatchesApplied(
+ PhabricatorStorageManagementAPI $api) {
$applied = $api->getAppliedPatches();
if ($applied === null) {
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php
@@ -15,7 +15,8 @@
}
public function didExecute(PhutilArgumentParser $args) {
- $api = $this->getAPI();
+ $api = $this->getAnyAPI();
+
$patches = $this->getPatches();
$databases = $api->getDatabaseList($patches, true);
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,6 +23,8 @@
public function didExecute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole();
+ $api = $this->getSingleAPI();
+
if (!$this->isDryRun() && !$this->isForce()) {
$console->writeOut(
phutil_console_wrap(
@@ -42,7 +44,6 @@
}
}
- $api = $this->getAPI();
$patches = $this->getPatches();
if ($args->getArg('unittest-fixtures')) {
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php
@@ -44,7 +44,7 @@
}
public function didExecute(PhutilArgumentParser $args) {
- $api = $this->getAPI();
+ $api = $this->getSingleAPI();
$patches = $this->getPatches();
$console = PhutilConsole::getConsole();
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php
@@ -15,13 +15,14 @@
}
public function didExecute(PhutilArgumentParser $args) {
+ $api = $this->getSingleAPI();
+
$console = PhutilConsole::getConsole();
$console->writeErr(
"%s\n",
pht('Analyzing table sizes (this may take a moment)...'));
- $api = $this->getAPI();
- $patches = $this->getPatches();
+ $patches = $this->getPatches();
$databases = $api->getDatabaseList($patches, true);
$conn_r = $api->getConn(null);
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php
@@ -36,7 +36,14 @@
$bin = dirname(phutil_get_library_root('phabricator')).'/bin/storage';
- if (!$this->getAPI()->isCharacterSetAvailable('utf8mb4')) {
+ // We don't care which database we're using to generate a quickstart file,
+ // since all of the schemata should be identical.
+ $api = $this->getAnyAPI();
+
+ $ref = $api->getRef();
+ $ref_key = $ref->getRefKey();
+
+ if (!$api->isCharacterSetAvailable('utf8mb4')) {
throw new PhutilArgumentUsageException(
pht(
'You can only generate a new quickstart file if MySQL supports '.
@@ -47,35 +54,39 @@
}
$err = phutil_passthru(
- '%s upgrade --force --no-quickstart --namespace %s',
+ '%s upgrade --force --no-quickstart --namespace %s --ref %s',
$bin,
- $namespace);
+ $namespace,
+ $ref_key);
if ($err) {
return $err;
}
$err = phutil_passthru(
- '%s adjust --force --namespace %s',
+ '%s adjust --force --namespace %s --ref %s',
$bin,
- $namespace);
+ $namespace,
+ $ref_key);
if ($err) {
return $err;
}
$tmp = new TempFile();
$err = phutil_passthru(
- '%s dump --namespace %s > %s',
+ '%s dump --namespace %s --ref %s > %s',
$bin,
$namespace,
+ $ref_key,
$tmp);
if ($err) {
return $err;
}
$err = phutil_passthru(
- '%s destroy --force --namespace %s',
+ '%s destroy --force --namespace %s --ref %s',
$bin,
- $namespace);
+ $namespace,
+ $ref_key);
if ($err) {
return $err;
}
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php
@@ -62,7 +62,7 @@
if (!strlen($input) && !$is_live) {
throw new PhutilArgumentUsageException(
pht(
- 'Specify the dumpfile to read with "--in", or use "--live" to '.
+ 'Specify the dumpfile to read with "--input", or use "--live" to '.
'generate one automatically.'));
}
@@ -108,11 +108,15 @@
}
if ($is_live) {
+ $api = $this->getSingleAPI();
+ $ref_key = $api->getRef()->getRefKey();
+
$root = dirname(phutil_get_library_root('phabricator'));
$future = new ExecFuture(
- '%R dump',
- $root.'/bin/storage');
+ '%R dump --ref %s',
+ $root.'/bin/storage',
+ $ref_key);
$lines = new LinesOfALargeExecFuture($future);
} else {
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php
@@ -15,7 +15,7 @@
}
public function execute(PhutilArgumentParser $args) {
- $api = $this->getAPI();
+ $api = $this->getSingleAPI();
list($host, $port) = $this->getBareHostAndPort($api->getHost());
$flag_port = $port
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php
@@ -15,50 +15,54 @@
}
public function didExecute(PhutilArgumentParser $args) {
- $api = $this->getAPI();
- $patches = $this->getPatches();
+ foreach ($this->getAPIs() as $api) {
+ $patches = $this->getPatches();
+ $applied = $api->getAppliedPatches();
- $applied = $api->getAppliedPatches();
+ if ($applied === null) {
+ echo phutil_console_format(
+ "**%s**: %s\n",
+ pht('Database Not Initialized'),
+ pht('Run **%s** to initialize.', './bin/storage upgrade'));
- if ($applied === null) {
- echo phutil_console_format(
- "**%s**: %s\n",
- pht('Database Not Initialized'),
- pht('Run **%s** to initialize.', './bin/storage upgrade'));
+ return 1;
+ }
- return 1;
- }
+ $ref = $api->getRef();
- $table = id(new PhutilConsoleTable())
- ->setShowHeader(false)
- ->addColumn('id', array('title' => pht('ID')))
- ->addColumn('status', array('title' => pht('Status')))
- ->addColumn('duration', array('title' => pht('Duration')))
- ->addColumn('type', array('title' => pht('Type')))
- ->addColumn('name', array('title' => pht('Name')));
+ $table = id(new PhutilConsoleTable())
+ ->setShowHeader(false)
+ ->addColumn('id', array('title' => pht('ID')))
+ ->addColumn('host', array('title' => pht('Host')))
+ ->addColumn('status', array('title' => pht('Status')))
+ ->addColumn('duration', array('title' => pht('Duration')))
+ ->addColumn('type', array('title' => pht('Type')))
+ ->addColumn('name', array('title' => pht('Name')));
- $durations = $api->getPatchDurations();
+ $durations = $api->getPatchDurations();
- foreach ($patches as $patch) {
- $duration = idx($durations, $patch->getFullKey());
- if ($duration === null) {
- $duration = '-';
- } else {
- $duration = pht('%s us', new PhutilNumber($duration));
+ foreach ($patches as $patch) {
+ $duration = idx($durations, $patch->getFullKey());
+ if ($duration === null) {
+ $duration = '-';
+ } else {
+ $duration = pht('%s us', new PhutilNumber($duration));
+ }
+
+ $table->addRow(array(
+ 'id' => $patch->getFullKey(),
+ 'host' => $ref->getRefKey(),
+ 'status' => in_array($patch->getFullKey(), $applied)
+ ? pht('Applied')
+ : pht('Not Applied'),
+ 'duration' => $duration,
+ 'type' => $patch->getType(),
+ 'name' => $patch->getName(),
+ ));
}
- $table->addRow(array(
- 'id' => $patch->getFullKey(),
- 'status' => in_array($patch->getFullKey(), $applied)
- ? pht('Applied')
- : pht('Not Applied'),
- 'duration' => $duration,
- 'type' => $patch->getType(),
- 'name' => $patch->getName(),
- ));
+ $table->draw();
}
-
- $table->draw();
return 0;
}
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php
@@ -73,16 +73,24 @@
$init_only = $args->getArg('init-only');
$no_adjust = $args->getArg('no-adjust');
- $this->upgradeSchemata($apply_only, $no_quickstart, $init_only);
+ $apis = $this->getMasterAPIs();
- if ($no_adjust || $init_only || $apply_only) {
- $console->writeOut(
- "%s\n",
- pht('Declining to apply storage adjustments.'));
- return 0;
- } else {
- return $this->adjustSchemata(false);
+ foreach ($apis as $api) {
+ $this->upgradeSchemata($api, $apply_only, $no_quickstart, $init_only);
+
+ if ($no_adjust || $init_only || $apply_only) {
+ $console->writeOut(
+ "%s\n",
+ pht('Declining to apply storage adjustments.'));
+ } else {
+ $err = $this->adjustSchemata($api, false);
+ if ($err) {
+ return $err;
+ }
+ }
}
+
+ return 0;
}
}
diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
--- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
+++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php
@@ -3,20 +3,56 @@
abstract class PhabricatorStorageManagementWorkflow
extends PhabricatorManagementWorkflow {
- private $api;
+ private $apis = array();
private $dryRun;
private $force;
private $patches;
private $didInitialize;
- final public function getAPI() {
- return $this->api;
+ final public function setAPIs(array $apis) {
+ $this->apis = $apis;
+ return $this;
}
- final public function setAPI(PhabricatorStorageManagementAPI $api) {
- $this->api = $api;
- return $this;
+ final public function getAnyAPI() {
+ return head($this->getAPIs());
+ }
+
+ final public function getMasterAPIs() {
+ $apis = $this->getAPIs();
+
+ $results = array();
+ foreach ($apis as $api) {
+ if ($api->getRef()->getIsMaster()) {
+ $results[] = $api;
+ }
+ }
+
+ if (!$results) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'This command only operates on database masters, but the selected '.
+ 'database hosts do not include any masters.'));
+ }
+
+ return $results;
+ }
+
+ final public function getSingleAPI() {
+ $apis = $this->getAPIs();
+ if (count($apis) == 1) {
+ return head($apis);
+ }
+
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Phabricator is configured in cluster mode, with multiple database '.
+ 'hosts. Use "--host" to specify which host you want to operate on.'));
+ }
+
+ final public function getAPIs() {
+ return $this->apis;
}
final protected function isDryRun() {
@@ -73,22 +109,34 @@
public function didExecute(PhutilArgumentParser $args) {}
- private function loadSchemata() {
- $query = id(new PhabricatorConfigSchemaQuery())
- ->setAPI($this->getAPI());
+ private function loadSchemata(PhabricatorStorageManagementAPI $api) {
+ $query = id(new PhabricatorConfigSchemaQuery());
+
+ $ref = $api->getRef();
+ $ref_key = $ref->getRefKey();
- $actual = $query->loadActualSchema();
- $expect = $query->loadExpectedSchema();
- $comp = $query->buildComparisonSchema($expect, $actual);
+ $query->setAPIs(array($api));
+ $query->setRefs(array($ref));
- return array($comp, $expect, $actual);
+ $actual = $query->loadActualSchemata();
+ $expect = $query->loadExpectedSchemata();
+ $comp = $query->buildComparisonSchemata($expect, $actual);
+
+ return array(
+ $comp[$ref_key],
+ $expect[$ref_key],
+ $actual[$ref_key],
+ );
}
- final protected function adjustSchemata($unsafe) {
- $lock = $this->lock();
+ final protected function adjustSchemata(
+ PhabricatorStorageManagementAPI $api,
+ $unsafe) {
+
+ $lock = $this->lock($api);
try {
- $err = $this->doAdjustSchemata($unsafe);
+ $err = $this->doAdjustSchemata($api, $unsafe);
} catch (Exception $ex) {
$lock->unlock();
throw $ex;
@@ -99,15 +147,19 @@
return $err;
}
- final private function doAdjustSchemata($unsafe) {
+ final private function doAdjustSchemata(
+ PhabricatorStorageManagementAPI $api,
+ $unsafe) {
+
$console = PhutilConsole::getConsole();
$console->writeOut(
"%s\n",
- pht('Verifying database schemata...'));
+ pht(
+ 'Verifying database schemata on "%s"...',
+ $api->getRef()->getRefKey()));
- list($adjustments, $errors) = $this->findAdjustments();
- $api = $this->getAPI();
+ list($adjustments, $errors) = $this->findAdjustments($api);
if (!$adjustments) {
$console->writeOut(
@@ -415,8 +467,9 @@
return $this->printErrors($errors, $err);
}
- private function findAdjustments() {
- list($comp, $expect, $actual) = $this->loadSchemata();
+ private function findAdjustments(
+ PhabricatorStorageManagementAPI $api) {
+ list($comp, $expect, $actual) = $this->loadSchemata($api);
$issue_charset = PhabricatorConfigStorageSchema::ISSUE_CHARSET;
$issue_collation = PhabricatorConfigStorageSchema::ISSUE_COLLATION;
@@ -766,14 +819,15 @@
}
final protected function upgradeSchemata(
+ PhabricatorStorageManagementAPI $api,
$apply_only = null,
$no_quickstart = false,
$init_only = false) {
- $lock = $this->lock();
+ $lock = $this->lock($api);
try {
- $this->doUpgradeSchemata($apply_only, $no_quickstart, $init_only);
+ $this->doUpgradeSchemata($api, $apply_only, $no_quickstart, $init_only);
} catch (Exception $ex) {
$lock->unlock();
throw $ex;
@@ -783,13 +837,12 @@
}
final private function doUpgradeSchemata(
+ PhabricatorStorageManagementAPI $api,
$apply_only,
$no_quickstart,
$init_only) {
- $api = $this->getAPI();
-
- $applied = $this->getApi()->getAppliedPatches();
+ $applied = $api->getAppliedPatches();
if ($applied === null) {
if ($this->dryRun) {
echo pht(
@@ -923,11 +976,13 @@
if (count($this->patches)) {
throw new Exception(
pht(
- 'Some patches could not be applied: %s',
+ 'Some patches could not be applied to "%s": %s',
+ $api->getRef()->getRefKey(),
implode(', ', array_keys($this->patches))));
} else if (!$this->dryRun && !$apply_only) {
echo pht(
- "Storage is up to date. Use '%s' for details.",
+ 'Storage is up to date on "%s". Use "%s" for details.',
+ $api->getRef()->getRefKey(),
'storage status')."\n";
}
break;
@@ -955,9 +1010,9 @@
*
* @return PhabricatorGlobalLock
*/
- final protected function lock() {
+ final protected function lock(PhabricatorStorageManagementAPI $api) {
return PhabricatorGlobalLock::newLock(__CLASS__)
- ->useSpecificConnection($this->getApi()->getConn(null))
+ ->useSpecificConnection($api->getConn(null))
->lock();
}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 10, 3:10 AM (1 w, 1 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/sd/mu/3j5gsioz7k6s3qac
Default Alt Text
D16848.id40570.diff (31 KB)

Event Timeline