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;
         }
     }
 }