Add relocate console command

This commit is contained in:
Hypolite Petovan 2022-05-15 21:41:39 -04:00
parent 7d09ce86c4
commit f1630ebb05
3 changed files with 208 additions and 1 deletions

205
src/Console/Relocate.php Normal file
View File

@ -0,0 +1,205 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Console;
use Asika\SimpleConsole\Console;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Worker;
use Friendica\Util\Strings;
use Friendica\Worker\Delivery;
class Relocate extends Console
{
protected $helpOptions = ['h', 'help', '?'];
/**
* @var IManageConfigValues
*/
private $config;
/**
* @var \Friendica\App\BaseURL
*/
private $baseUrl;
/**
* @var \Friendica\Database\Database
*/
private $database;
protected function getHelp()
{
$help = <<<HELP
console relocate - Update the node base URL
Usage
bin/console relocate <new base URL> [-h|--help|-?] [-v]
Description
Warning! Advanced function. Could make this server unreachable.
Change the base URL for this server. Sends relocation message to all the Friendica and Diaspora* contacts of all local users.
This process updates all the database fields that may contain a URL pointing at the current domain, as a result it takes
a while and the node will be in maintenance mode for the whole duration.
Options
-h|--help|-? Show help information
-v Show more debug information.
HELP;
return $help;
}
public function __construct(\Friendica\App\BaseURL $baseUrl, \Friendica\Database\Database $database, IManageConfigValues $config, $argv = null)
{
parent::__construct($argv);
$this->baseUrl = $baseUrl;
$this->database = $database;
$this->config = $config;
}
protected function doExecute()
{
if (count($this->args) == 0) {
$this->out($this->getHelp());
return 0;
}
if (count($this->args) > 1) {
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
}
$new_url = rtrim($this->getArgument(0), '/');
$parsed = @parse_url($new_url);
if (!is_array($parsed) || empty($parsed['host']) || empty($parsed['scheme'])) {
throw new \InvalidArgumentException('Can not parse new base URL. Must have at least <scheme>://<domain>');
}
$this->out(sprintf('Relocation started from %s to %s. Could take a while to complete.', $this->baseUrl->get(true), $this->getArgument(0)));
$old_url = $this->baseUrl->get(true);
// Generate host names for relocation the addresses in the format user@address.tld
$new_host = str_replace('http://', '@', Strings::normaliseLink($new_url));
$old_host = str_replace('http://', '@', Strings::normaliseLink($old_url));
$this->out('Entering maintenance mode');
$this->config->set('system', 'maintenance', true);
$this->config->set('system', 'maintenance_reason', 'Relocating node to ' . $new_url);
try {
if (!$this->database->transaction()) {
throw new \Exception('Unable to start a transaction, please retry later.');
}
// update tables
$this->out('Updating apcontact table fields');
$this->database->replaceInTableFields('apcontact', ['url', 'inbox', 'outbox', 'sharedinbox', 'photo', 'header', 'alias', 'subscribe', 'baseurl'], $old_url, $new_url);
$this->database->replaceInTableFields('apcontact', ['addr'], $old_host, $new_host);
$this->out('Updating contact table fields');
$this->database->replaceInTableFields('contact', ['photo', 'thumb', 'micro', 'url', 'alias', 'request', 'batch', 'notify', 'poll', 'subscribe', 'baseurl', 'confirm', 'poco', 'avatar', 'header'], $old_url, $new_url);
$this->database->replaceInTableFields('contact', ['nurl'], Strings::normaliseLink($old_url), Strings::normaliseLink($new_url));
$this->database->replaceInTableFields('contact', ['addr'], $old_host, $new_host);
$this->out('Updating conv table fields');
$this->database->replaceInTableFields('conv', ['creator', 'recips'], $old_host, $new_host);
$this->out('Updating delayed-post table fields');
$this->database->replaceInTableFields('delayed-post', ['uri'], $old_url, $new_url);
$this->out('Updating endpoint table fields');
$this->database->replaceInTableFields('endpoint', ['url'], $old_url, $new_url);
$this->out('Updating event table fields');
$this->database->replaceInTableFields('event', ['uri'], $old_url, $new_url);
$this->out('Updating fcontact table fields');
$this->database->replaceInTableFields('fcontact', ['url', 'photo', 'request', 'batch', 'poll', 'confirm', 'alias'], $old_url, $new_url);
$this->database->replaceInTableFields('fcontact', ['addr'], $old_host, $new_host);
$this->out('Updating fsuggest table fields');
$this->database->replaceInTableFields('fsuggest', ['url', 'request', 'photo'], $old_url, $new_url);
$this->out('Updating gserver table fields');
$this->database->replaceInTableFields('gserver', ['url'], $old_url, $new_url);
$this->database->replaceInTableFields('gserver', ['nurl'], Strings::normaliseLink($old_url), Strings::normaliseLink($new_url));
$this->out('Updating inbox-status table fields');
$this->database->replaceInTableFields('inbox-status', ['url'], $old_url, $new_url);
$this->out('Updating item-uri table fields');
$this->database->replaceInTableFields('item-uri', ['uri'], $old_url, $new_url);
$this->out('Updating mail table fields');
$this->database->replaceInTableFields('mail', ['from-photo', 'from-url', 'uri', 'thr-parent'], $old_url, $new_url);
$this->database->replaceInTableFields('mail', ['parent-uri'], $old_host, $new_host);
$this->out('Updating notify table fields');
$this->database->replaceInTableFields('notify', ['url', 'photo', 'link', 'msg', 'name_cache', 'msg_cache'], $old_url, $new_url);
$this->out('Updating profile table fields');
$this->database->replaceInTableFields('profile', ['photo', 'thumb'], $old_url, $new_url);
$this->out('Updating post-content table fields');
$this->database->replaceInTableFields('post-content', ['body', 'raw-body', 'rendered-html', 'target', 'plink'], $old_url, $new_url);
$this->database->replaceInTableFields('post-content', ['body', 'raw-body', 'rendered-html', 'target'], $old_host, $new_host);
$this->out('Updating post-history table fields');
$this->database->replaceInTableFields('post-history', ['body', 'raw-body', 'rendered-html', 'target', 'plink'], $old_url, $new_url);
$this->database->replaceInTableFields('post-history', ['body', 'raw-body', 'rendered-html', 'target'], $old_host, $new_host);
$this->out('Updating post-link table fields');
$this->database->replaceInTableFields('post-link', ['url'], $old_url, $new_url);
$this->out('Updating post-media table fields');
$this->database->replaceInTableFields('post-media', ['url', 'preview', 'author-url', 'author-image', 'publisher-url', 'publisher-image'], $old_url, $new_url);
$this->out('Updating tag table fields');
$this->database->replaceInTableFields('tag', ['url'], $old_url, $new_url);
// update config
$this->out('Updating config values');
$this->config->set('system', 'url', $new_url);
$this->baseUrl->saveByURL($new_url);
$this->database->commit();
} catch (\Throwable $e) {
$this->database->rollback();
$this->out('Process aborted with message: ' . $e->getMessage() . ' thrown in ' . $e->getFile() . ':' . $e->getLine());
return 1;
} finally {
$this->out('Leaving maintenance mode');
$this->config->set('system', 'maintenance', false);
$this->config->set('system', 'maintenance_reason', '');
}
// send relocate
$this->out('Schedule relocation messages to remote Friendica and Diaspora hosts');
$users = $this->database->selectToArray('user', ['uid'], ['account_removed' => false, 'account_expired' => false]);
foreach ($users as $user) {
Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, $user['uid']);
}
return 0;
}
}

View File

@ -65,6 +65,7 @@ Commands:
po2php Generate a strings.php file from a messages.po file po2php Generate a strings.php file from a messages.po file
typo Checks for parse errors in Friendica files typo Checks for parse errors in Friendica files
postupdate Execute pending post update scripts (can last days) postupdate Execute pending post update scripts (can last days)
relocate Update node base URL
serverblock Manage blocked servers serverblock Manage blocked servers
storage Manage storage backend storage Manage storage backend
relay Manage ActivityPub relay servers relay Manage ActivityPub relay servers
@ -97,6 +98,7 @@ HELP;
'postupdate' => Friendica\Console\PostUpdate::class, 'postupdate' => Friendica\Console\PostUpdate::class,
'po2php' => Friendica\Console\PoToPhp::class, 'po2php' => Friendica\Console\PoToPhp::class,
'relay' => Friendica\Console\Relay::class, 'relay' => Friendica\Console\Relay::class,
'relocate' => Friendica\Console\Relocate::class,
'serverblock' => Friendica\Console\ServerBlock::class, 'serverblock' => Friendica\Console\ServerBlock::class,
'storage' => Friendica\Console\Storage::class, 'storage' => Friendica\Console\Storage::class,
'test' => Friendica\Console\Test::class, 'test' => Friendica\Console\Test::class,

View File

@ -1153,7 +1153,7 @@ class Database
* *
* @return boolean Was the command executed successfully? * @return boolean Was the command executed successfully?
*/ */
public function transaction() public function transaction(): bool
{ {
if (!$this->performCommit()) { if (!$this->performCommit()) {
return false; return false;