Files
phabricator/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php
epriestley bc15eee3f2 Update SchemaQuery and the web UI to accommodate multiple master databases
Summary:
Depends on D16115. Ref T11044. In the brave new world of multiple masters, we need to check the schemata on each master when looking for missing storage patches, keys, schema changes, etc.

This realigns all the "check out what's up with that schema" calls to work for multiple hosts, and updates the web UI to include a "Server" column and allow you to browse per-server.

This doesn't update `bin/storage`, so it breaks things on its own (and unit tests probably won't pass). I'll update that in the next change.

Test Plan: Configured local environment in cluster mode with multiple masters, saw both hosts' status reported in web UI.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T11044

Differential Revision: https://secure.phabricator.com/D16847
2016-11-12 16:36:52 -08:00

182 lines
4.7 KiB
PHP

<?php
final class PhabricatorConfigDatabaseIssueController
extends PhabricatorConfigDatabaseController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$query = new PhabricatorConfigSchemaQuery();
$actual = $query->loadActualSchemata();
$expect = $query->loadExpectedSchemata();
$comp_servers = $query->buildComparisonSchemata($expect, $actual);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Database Issues'));
$crumbs->setBorder(true);
// Collect all open issues.
$issues = array();
foreach ($comp_servers as $ref_name => $comp) {
foreach ($comp->getDatabases() as $database_name => $database) {
foreach ($database->getLocalIssues() as $issue) {
$issues[] = array(
$ref_name,
$database_name,
null,
null,
null,
$issue,
);
}
foreach ($database->getTables() as $table_name => $table) {
foreach ($table->getLocalIssues() as $issue) {
$issues[] = array(
$ref_name,
$database_name,
$table_name,
null,
null,
$issue,
);
}
foreach ($table->getColumns() as $column_name => $column) {
foreach ($column->getLocalIssues() as $issue) {
$issues[] = array(
$ref_name,
$database_name,
$table_name,
'column',
$column_name,
$issue,
);
}
}
foreach ($table->getKeys() as $key_name => $key) {
foreach ($key->getLocalIssues() as $issue) {
$issues[] = array(
$ref_name,
$database_name,
$table_name,
'key',
$key_name,
$issue,
);
}
}
}
}
}
// Sort all open issues so that the most severe issues appear first.
$order = array();
$counts = array();
foreach ($issues as $key => $issue) {
$const = $issue[5];
$status = PhabricatorConfigStorageSchema::getIssueStatus($const);
$severity = PhabricatorConfigStorageSchema::getStatusSeverity($status);
$order[$key] = sprintf(
'~%d~%s%s%s',
9 - $severity,
$issue[1],
$issue[2],
$issue[4]);
if (empty($counts[$status])) {
$counts[$status] = 0;
}
$counts[$status]++;
}
asort($order);
$issues = array_select_keys($issues, array_keys($order));
// Render the issues.
$rows = array();
foreach ($issues as $issue) {
$const = $issue[5];
$uri = $this->getApplicationURI('/database/'.$issue[0].'/'.$issue[1].'/');
$database_link = phutil_tag(
'a',
array(
'href' => $uri,
),
$issue[1]);
$rows[] = array(
$this->renderIcon(
PhabricatorConfigStorageSchema::getIssueStatus($const)),
$issue[0],
$database_link,
$issue[2],
$issue[3],
$issue[4],
PhabricatorConfigStorageSchema::getIssueDescription($const),
);
}
$table = id(new AphrontTableView($rows))
->setNoDataString(
pht('No databases have any issues.'))
->setHeaders(
array(
null,
pht('Server'),
pht('Database'),
pht('Table'),
pht('Type'),
pht('Column/Key'),
pht('Issue'),
))
->setColumnClasses(
array(
null,
null,
null,
null,
null,
null,
'wide',
));
$errors = array();
if (isset($counts[PhabricatorConfigStorageSchema::STATUS_FAIL])) {
$errors[] = pht(
'Detected %s serious issue(s) with the schemata.',
new PhutilNumber($counts[PhabricatorConfigStorageSchema::STATUS_FAIL]));
}
if (isset($counts[PhabricatorConfigStorageSchema::STATUS_WARN])) {
$errors[] = pht(
'Detected %s warning(s) with the schemata.',
new PhutilNumber($counts[PhabricatorConfigStorageSchema::STATUS_WARN]));
}
$title = pht('Database Issues');
$header = id(new PHUIHeaderView())
->setHeader($title)
->setProfileHeader(true);
$nav = $this->buildSideNavView();
$nav->selectFilter('dbissue/');
$content = id(new PhabricatorConfigPageView())
->setHeader($header)
->setContent($table);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setNavigation($nav)
->appendChild($content)
->addClass('white-background');
}
}