Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F19906027
D16848.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
31 KB
Referenced Files
None
Subscribers
None
D16848.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 1, 9:17 PM (2 w, 1 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/ep/k7/ukcbicl6nakffsx7
Default Alt Text
D16848.diff (31 KB)
Attached To
Mode
D16848: Update `bin/storage` workflows to accommodate multiple masters
Attached
Detach File
Event Timeline
Log In to Comment