2012-12-30 15:37:49 +01:00
|
|
|
<?php
|
|
|
|
|
2015-06-15 10:02:26 +02:00
|
|
|
final class PhabricatorSetupIssue extends Phobject {
|
2012-12-30 15:37:49 +01:00
|
|
|
|
|
|
|
private $issueKey;
|
|
|
|
private $name;
|
|
|
|
private $message;
|
|
|
|
private $isFatal;
|
|
|
|
private $summary;
|
|
|
|
private $shortName;
|
2015-02-10 21:53:00 +01:00
|
|
|
private $group;
|
2016-11-21 18:07:47 +01:00
|
|
|
private $databaseRef;
|
2012-12-30 15:37:49 +01:00
|
|
|
|
2013-02-22 18:21:01 +01:00
|
|
|
private $isIgnored = false;
|
2012-12-30 15:37:49 +01:00
|
|
|
private $phpExtensions = array();
|
|
|
|
private $phabricatorConfig = array();
|
2013-04-10 22:10:52 +02:00
|
|
|
private $relatedPhabricatorConfig = array();
|
2012-12-30 15:37:49 +01:00
|
|
|
private $phpConfig = array();
|
|
|
|
private $commands = array();
|
2014-08-25 20:41:40 +02:00
|
|
|
private $mysqlConfig = array();
|
2014-09-04 21:48:34 +02:00
|
|
|
private $originalPHPConfigValues = array();
|
2015-01-29 23:28:49 +01:00
|
|
|
private $links;
|
2012-12-30 15:37:49 +01:00
|
|
|
|
2016-09-06 21:52:03 +02:00
|
|
|
public static function newDatabaseConnectionIssue(
|
2016-11-23 19:29:53 +01:00
|
|
|
Exception $ex,
|
Run "DatabaseSetup" checks against all configured hosts
Summary:
Ref T10759. Currently, these checks run only against configured masters. Instead, check every host.
These checks also sort of cheat through restart during a recovery, when some hosts will be unreachable: they test for "disaster" by seeing if no masters are reachable, and just skip all the checks in that case.
This is bad for at least two reasons:
- After recent changes, it is possible that //some// masters are dead but it's still OK to start. For example, "slowvote" may have no master, but everything else is reachable. We can safely run without slowvote.
- It's possible to start during a disaster and miss important setup checks completely, since we skip them, get a clean bill of health, and never re-test them.
Instead:
- Test each host individually.
- Fundamental problems (lack of InnoDB, bad schema) are fatal on any host.
- If we can't connect, raise it as a //warning// to make sure we check it later. If you start during a disaster, we still want to make sure that schemata are up to date if you later recover a host.
In particular, I'm going to add these checks soon:
- Fatal if a "master" is replicating.
- Fatal if a "replica" is not replicating.
- Fatal if a database partition config differs from web partition config.
- When we let a database off with a warning because it's down, and later upgrade it to a fatal because we discover it is broken after it comes up again, fatal everything. Currently, we keep running if we "discover" the presence of new fatals after surviving setup checks for the first time.
Test Plan:
- Configured with multiple masters, intentionally broke one (simulating a disaster where one master is lost), saw Phabricator still startup.
- Tested individual setup checks by intentionally breaking them.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10759
Differential Revision: https://secure.phabricator.com/D16902
2016-11-21 14:13:54 +01:00
|
|
|
$is_fatal) {
|
2016-09-06 21:52:03 +02:00
|
|
|
|
|
|
|
$message = pht(
|
|
|
|
"Unable to connect to MySQL!\n\n".
|
|
|
|
"%s\n\n".
|
|
|
|
"Make sure Phabricator and MySQL are correctly configured.",
|
|
|
|
$ex->getMessage());
|
|
|
|
|
Run "DatabaseSetup" checks against all configured hosts
Summary:
Ref T10759. Currently, these checks run only against configured masters. Instead, check every host.
These checks also sort of cheat through restart during a recovery, when some hosts will be unreachable: they test for "disaster" by seeing if no masters are reachable, and just skip all the checks in that case.
This is bad for at least two reasons:
- After recent changes, it is possible that //some// masters are dead but it's still OK to start. For example, "slowvote" may have no master, but everything else is reachable. We can safely run without slowvote.
- It's possible to start during a disaster and miss important setup checks completely, since we skip them, get a clean bill of health, and never re-test them.
Instead:
- Test each host individually.
- Fundamental problems (lack of InnoDB, bad schema) are fatal on any host.
- If we can't connect, raise it as a //warning// to make sure we check it later. If you start during a disaster, we still want to make sure that schemata are up to date if you later recover a host.
In particular, I'm going to add these checks soon:
- Fatal if a "master" is replicating.
- Fatal if a "replica" is not replicating.
- Fatal if a database partition config differs from web partition config.
- When we let a database off with a warning because it's down, and later upgrade it to a fatal because we discover it is broken after it comes up again, fatal everything. Currently, we keep running if we "discover" the presence of new fatals after surviving setup checks for the first time.
Test Plan:
- Configured with multiple masters, intentionally broke one (simulating a disaster where one master is lost), saw Phabricator still startup.
- Tested individual setup checks by intentionally breaking them.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10759
Differential Revision: https://secure.phabricator.com/D16902
2016-11-21 14:13:54 +01:00
|
|
|
$issue = id(new self())
|
2016-09-06 21:52:03 +02:00
|
|
|
->setIssueKey('mysql.connect')
|
|
|
|
->setName(pht('Can Not Connect to MySQL'))
|
|
|
|
->setMessage($message)
|
Run "DatabaseSetup" checks against all configured hosts
Summary:
Ref T10759. Currently, these checks run only against configured masters. Instead, check every host.
These checks also sort of cheat through restart during a recovery, when some hosts will be unreachable: they test for "disaster" by seeing if no masters are reachable, and just skip all the checks in that case.
This is bad for at least two reasons:
- After recent changes, it is possible that //some// masters are dead but it's still OK to start. For example, "slowvote" may have no master, but everything else is reachable. We can safely run without slowvote.
- It's possible to start during a disaster and miss important setup checks completely, since we skip them, get a clean bill of health, and never re-test them.
Instead:
- Test each host individually.
- Fundamental problems (lack of InnoDB, bad schema) are fatal on any host.
- If we can't connect, raise it as a //warning// to make sure we check it later. If you start during a disaster, we still want to make sure that schemata are up to date if you later recover a host.
In particular, I'm going to add these checks soon:
- Fatal if a "master" is replicating.
- Fatal if a "replica" is not replicating.
- Fatal if a database partition config differs from web partition config.
- When we let a database off with a warning because it's down, and later upgrade it to a fatal because we discover it is broken after it comes up again, fatal everything. Currently, we keep running if we "discover" the presence of new fatals after surviving setup checks for the first time.
Test Plan:
- Configured with multiple masters, intentionally broke one (simulating a disaster where one master is lost), saw Phabricator still startup.
- Tested individual setup checks by intentionally breaking them.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10759
Differential Revision: https://secure.phabricator.com/D16902
2016-11-21 14:13:54 +01:00
|
|
|
->setIsFatal($is_fatal)
|
2016-09-06 21:52:03 +02:00
|
|
|
->addRelatedPhabricatorConfig('mysql.host')
|
|
|
|
->addRelatedPhabricatorConfig('mysql.port')
|
|
|
|
->addRelatedPhabricatorConfig('mysql.user')
|
|
|
|
->addRelatedPhabricatorConfig('mysql.pass');
|
Run "DatabaseSetup" checks against all configured hosts
Summary:
Ref T10759. Currently, these checks run only against configured masters. Instead, check every host.
These checks also sort of cheat through restart during a recovery, when some hosts will be unreachable: they test for "disaster" by seeing if no masters are reachable, and just skip all the checks in that case.
This is bad for at least two reasons:
- After recent changes, it is possible that //some// masters are dead but it's still OK to start. For example, "slowvote" may have no master, but everything else is reachable. We can safely run without slowvote.
- It's possible to start during a disaster and miss important setup checks completely, since we skip them, get a clean bill of health, and never re-test them.
Instead:
- Test each host individually.
- Fundamental problems (lack of InnoDB, bad schema) are fatal on any host.
- If we can't connect, raise it as a //warning// to make sure we check it later. If you start during a disaster, we still want to make sure that schemata are up to date if you later recover a host.
In particular, I'm going to add these checks soon:
- Fatal if a "master" is replicating.
- Fatal if a "replica" is not replicating.
- Fatal if a database partition config differs from web partition config.
- When we let a database off with a warning because it's down, and later upgrade it to a fatal because we discover it is broken after it comes up again, fatal everything. Currently, we keep running if we "discover" the presence of new fatals after surviving setup checks for the first time.
Test Plan:
- Configured with multiple masters, intentionally broke one (simulating a disaster where one master is lost), saw Phabricator still startup.
- Tested individual setup checks by intentionally breaking them.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10759
Differential Revision: https://secure.phabricator.com/D16902
2016-11-21 14:13:54 +01:00
|
|
|
|
|
|
|
if (PhabricatorEnv::getEnvConfig('cluster.databases')) {
|
|
|
|
$issue->addRelatedPhabricatorConfig('cluster.databases');
|
|
|
|
}
|
|
|
|
|
|
|
|
return $issue;
|
2016-09-06 21:52:03 +02:00
|
|
|
}
|
|
|
|
|
2012-12-30 15:37:49 +01:00
|
|
|
public function addCommand($command) {
|
|
|
|
$this->commands[] = $command;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCommands() {
|
|
|
|
return $this->commands;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setShortName($short_name) {
|
|
|
|
$this->shortName = $short_name;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getShortName() {
|
|
|
|
if ($this->shortName === null) {
|
|
|
|
return $this->getName();
|
|
|
|
}
|
|
|
|
return $this->shortName;
|
|
|
|
}
|
|
|
|
|
2016-11-21 18:07:47 +01:00
|
|
|
public function setDatabaseRef(PhabricatorDatabaseRef $database_ref) {
|
|
|
|
$this->databaseRef = $database_ref;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getDatabaseRef() {
|
|
|
|
return $this->databaseRef;
|
|
|
|
}
|
|
|
|
|
2015-02-10 21:53:00 +01:00
|
|
|
public function setGroup($group) {
|
|
|
|
$this->group = $group;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getGroup() {
|
|
|
|
if ($this->group) {
|
|
|
|
return $this->group;
|
|
|
|
} else {
|
|
|
|
return PhabricatorSetupCheck::GROUP_OTHER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-30 15:37:49 +01:00
|
|
|
public function setName($name) {
|
|
|
|
$this->name = $name;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getName() {
|
|
|
|
return $this->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setSummary($summary) {
|
|
|
|
$this->summary = $summary;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getSummary() {
|
|
|
|
if ($this->summary === null) {
|
|
|
|
return $this->getMessage();
|
|
|
|
}
|
|
|
|
return $this->summary;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setIssueKey($issue_key) {
|
|
|
|
$this->issueKey = $issue_key;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getIssueKey() {
|
|
|
|
return $this->issueKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setIsFatal($is_fatal) {
|
|
|
|
$this->isFatal = $is_fatal;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getIsFatal() {
|
|
|
|
return $this->isFatal;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addPHPConfig($php_config) {
|
|
|
|
$this->phpConfig[] = $php_config;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-09-04 21:48:34 +02:00
|
|
|
/**
|
|
|
|
* Set an explicit value to display when showing the user PHP configuration
|
|
|
|
* values.
|
|
|
|
*
|
|
|
|
* If Phabricator has changed a value by the time a config issue is raised,
|
|
|
|
* you can provide the original value here so the UI makes sense. For example,
|
|
|
|
* we alter `memory_limit` during startup, so if the original value is not
|
|
|
|
* provided it will look like it is always set to `-1`.
|
|
|
|
*
|
|
|
|
* @param string PHP configuration option to provide a value for.
|
|
|
|
* @param string Explicit value to show in the UI.
|
|
|
|
* @return this
|
|
|
|
*/
|
|
|
|
public function addPHPConfigOriginalValue($php_config, $value) {
|
|
|
|
$this->originalPHPConfigValues[$php_config] = $value;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPHPConfigOriginalValue($php_config, $default = null) {
|
|
|
|
return idx($this->originalPHPConfigValues, $php_config, $default);
|
|
|
|
}
|
|
|
|
|
2012-12-30 15:37:49 +01:00
|
|
|
public function getPHPConfig() {
|
|
|
|
return $this->phpConfig;
|
|
|
|
}
|
|
|
|
|
2014-08-25 20:41:40 +02:00
|
|
|
public function addMySQLConfig($mysql_config) {
|
|
|
|
$this->mysqlConfig[] = $mysql_config;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getMySQLConfig() {
|
|
|
|
return $this->mysqlConfig;
|
|
|
|
}
|
|
|
|
|
2012-12-30 15:37:49 +01:00
|
|
|
public function addPhabricatorConfig($phabricator_config) {
|
|
|
|
$this->phabricatorConfig[] = $phabricator_config;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPhabricatorConfig() {
|
|
|
|
return $this->phabricatorConfig;
|
|
|
|
}
|
|
|
|
|
2013-04-10 22:10:52 +02:00
|
|
|
public function addRelatedPhabricatorConfig($phabricator_config) {
|
|
|
|
$this->relatedPhabricatorConfig[] = $phabricator_config;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getRelatedPhabricatorConfig() {
|
|
|
|
return $this->relatedPhabricatorConfig;
|
|
|
|
}
|
|
|
|
|
2012-12-30 15:37:49 +01:00
|
|
|
public function addPHPExtension($php_extension) {
|
|
|
|
$this->phpExtensions[] = $php_extension;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPHPExtensions() {
|
|
|
|
return $this->phpExtensions;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setMessage($message) {
|
|
|
|
$this->message = $message;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getMessage() {
|
|
|
|
return $this->message;
|
|
|
|
}
|
|
|
|
|
2013-02-22 18:21:01 +01:00
|
|
|
public function setIsIgnored($is_ignored) {
|
|
|
|
$this->isIgnored = $is_ignored;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getIsIgnored() {
|
|
|
|
return $this->isIgnored;
|
|
|
|
}
|
2015-01-29 23:28:49 +01:00
|
|
|
|
|
|
|
public function addLink($href, $name) {
|
|
|
|
$this->links[] = array(
|
|
|
|
'href' => $href,
|
|
|
|
'name' => $name,
|
|
|
|
);
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getLinks() {
|
|
|
|
return $this->links;
|
|
|
|
}
|
|
|
|
|
2012-12-30 15:37:49 +01:00
|
|
|
}
|