private function newClusterConnection($database, $mode) { $master = PhabricatorDatabaseRef::getMasterDatabaseRef(); if ($master && !$master->isSevered()) { $connection = $master->newApplicationConnection($database); if ($master->isReachable($connection)) { return $connection; } else { if ($mode == 'w') { $this->raiseImpossibleWrite($database); } PhabricatorEnv::setReadOnly(true, PhabricatorEnv::READONLY_UNREACHABLE); } } $replica = PhabricatorDatabaseRef::getReplicaDatabaseRef(); if (!$replica) { throw new Exception(pht('No valid databases are configured!')); } $connection = $replica->newApplicationConnection($database); $connection->setReadOnly(true); if ($replica->isReachable($connection)) { return $connection; } $this->raiseUnreachable($database); }
protected function buildSchemaQuery() { $ref = PhabricatorDatabaseRef::getMasterDatabaseRef(); $api = id(new PhabricatorStorageManagementAPI())->setUser($ref->getUser())->setHost($ref->getHost())->setPort($ref->getPort())->setNamespace(PhabricatorLiskDAO::getDefaultStorageNamespace())->setPassword($ref->getPass()); $query = id(new PhabricatorConfigSchemaQuery())->setAPI($api); return $query; }
protected function executeChecks() { $master = PhabricatorDatabaseRef::getMasterDatabaseRef(); if (!$master) { // If we're implicitly in read-only mode during disaster recovery, // don't bother with these setup checks. return; } $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 ($database_exception) { $issue = PhabricatorSetupIssue::newDatabaseConnectionIssue($database_exception); $this->addIssue($issue); return; } $engines = queryfx_all($conn_raw, 'SHOW ENGINES'); $engines = ipull($engines, 'Support', 'Engine'); $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." . "\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.)"); $this->newIssue('mysql.innodb')->setName(pht('MySQL InnoDB Engine Not Available'))->setMessage($message)->setIsFatal(true); return; } $namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace'); $databases = queryfx_all($conn_raw, 'SHOW DATABASES'); $databases = ipull($databases, 'Database', 'Database'); if (empty($databases[$namespace . '_meta_data'])) { $message = pht("Run the storage upgrade script to setup Phabricator's database " . "schema."); $this->newIssue('storage.upgrade')->setName(pht('Setup MySQL Schema'))->setMessage($message)->setIsFatal(true)->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade')); } else { $conn_meta = $master->newApplicationConnection($namespace . '_meta_data'); $applied = queryfx_all($conn_meta, 'SELECT patch FROM patch_status'); $applied = ipull($applied, 'patch', 'patch'); $all = PhabricatorSQLPatchList::buildAllPatches(); $diff = array_diff_key($all, $applied); if ($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))))->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade')); } } $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)); } }
$refs = PhabricatorDatabaseRef::getLiveRefs(); // 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. $refs[] = PhabricatorDatabaseRef::getMasterDatabaseRef(); foreach ($refs as $possible_ref) { if ($possible_ref->getHost() == $host) { $ref = $possible_ref; break; } } if (!$ref) { throw new PhutilArgumentUsageException(pht('There is no configured database on host "%s". This command can ' . 'only interact with configured databases.', $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); }
private static function buildConfigurationSourceStack($config_optional) { self::dropConfigCache(); $stack = new PhabricatorConfigStackSource(); self::$sourceStack = $stack; $default_source = id(new PhabricatorConfigDefaultSource())->setName(pht('Global Default')); $stack->pushSource($default_source); $env = self::getSelectedEnvironmentName(); if ($env) { $stack->pushSource(id(new PhabricatorConfigFileSource($env))->setName(pht("File '%s'", $env))); } $stack->pushSource(id(new PhabricatorConfigLocalSource())->setName(pht('Local Config'))); // If the install overrides the database adapter, we might need to load // the database adapter class before we can push on the database config. // This config is locked and can't be edited from the web UI anyway. foreach (self::getEnvConfig('load-libraries') as $library) { phutil_load_library($library); } // If custom libraries specify config options, they won't get default // values as the Default source has already been loaded, so we get it to // pull in all options from non-phabricator libraries now they are loaded. $default_source->loadExternalOptions(); // If this install has site config sources, load them now. $site_sources = id(new PhutilClassMapQuery())->setAncestorClass('PhabricatorConfigSiteSource')->setSortMethod('getPriority')->execute(); foreach ($site_sources as $site_source) { $stack->pushSource($site_source); } $master = PhabricatorDatabaseRef::getMasterDatabaseRef(); if (!$master) { self::setReadOnly(true, self::READONLY_MASTERLESS); } else { if ($master->isSevered()) { $master->checkHealth(); if ($master->isSevered()) { self::setReadOnly(true, self::READONLY_SEVERED); } } } try { $stack->pushSource(id(new PhabricatorConfigDatabaseSource('default'))->setName(pht('Database'))); } catch (AphrontSchemaQueryException $exception) { // If the database is not available, just skip this configuration // source. This happens during `bin/storage upgrade`, `bin/conf` before // schema setup, etc. } catch (AphrontConnectionQueryException $ex) { if (!$config_optional) { throw $ex; } } catch (AphrontInvalidCredentialsQueryException $ex) { if (!$config_optional) { throw $ex; } } }