%PDF- %PDF-
Direktori : /www/varak.net/wiki.varak.net/extensions/CirrusSearch/includes/Maintenance/ |
Current File : /www/varak.net/wiki.varak.net/extensions/CirrusSearch/includes/Maintenance/ConfigUtils.php |
<?php namespace CirrusSearch\Maintenance; use Elastica\Client; /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html */ class ConfigUtils { /** * @var Client */ private $client; /** * @var Maintenance */ private $out; /** * @param Client $client * @param Maintenance $out */ public function __construct( Client $client, Maintenance $out ) { $this->client = $client; $this->out = $out; } public function checkElasticsearchVersion() { $this->outputIndented( 'Fetching Elasticsearch version...' ); $result = $this->client->request( '' ); $result = $result->getData(); if ( !isset( $result['version']['number'] ) ) { $this->error( 'unable to determine, aborting.', 1 ); } $result = $result[ 'version' ][ 'number' ]; $this->output( "$result..." ); if ( !preg_match( '/^2./', $result ) ) { $this->output( "Not supported!\n" ); $this->error( "Only Elasticsearch 2.x is supported. Your version: $result.", 1 ); } else { $this->output( "ok\n" ); } } /** * Pick the index identifier from the provided command line option. * * @param string $option command line option * 'now' => current time * 'current' => if there is just one index for this type then use its identifier * other string => that string back * @param string $typeName * @return string index identifier to use */ public function pickIndexIdentifierFromOption( $option, $typeName ) { if ( $option === 'now' ) { $identifier = strval( time() ); $this->outputIndented( "Setting index identifier...${typeName}_${identifier}\n" ); return $identifier; } if ( $option === 'current' ) { $this->outputIndented( 'Inferring index identifier...' ); $found = $this->getAllIndicesByType( $typeName ); if ( count( $found ) > 1 ) { $this->output( "error\n" ); $this->error( "Looks like the index has more than one identifier. You should delete all\n" . "but the one of them currently active. Here is the list: " . implode( ',', $found ), 1 ); } if ( $found ) { $identifier = substr( $found[0], strlen( $typeName ) + 1 ); if ( !$identifier ) { // This happens if there is an index named what the alias should be named. // If the script is run with --startOver it should nuke it. $identifier = 'first'; } } else { $identifier = 'first'; } $this->output( "${typeName}_${identifier}\n"); return $identifier; } return $option; } /** * Scan the indices and return the ones that match the * type $typeName * * @param string $typeName the type to filter with * @return string[] the list of indices */ public function getAllIndicesByType( $typeName ) { $found = []; foreach ( $this->client->getStatus()->getIndexNames() as $name ) { if ( substr( $name, 0, strlen( $typeName ) ) === $typeName ) { $found[] = $name; } } return $found; } /** * @param string $what generally plugins or modules * @return string[] list of modules or plugins */ private function scanModulesOrPlugins( $what ) { $result = $this->client->request( '_nodes' ); $result = $result->getData(); $availables = []; $first = true; foreach ( array_values( $result[ 'nodes' ] ) as $node ) { $plugins = []; foreach ( $node[ $what ] as $plugin ) { $plugins[] = $plugin[ 'name' ]; } if ( $first ) { $availables = $plugins; $first = false; } else { $availables = array_intersect( $availables, $plugins ); } } return $availables; } /** * @param string[] $bannedPlugins * @return string[] */ public function scanAvailablePlugins( array $bannedPlugins = [] ) { $this->outputIndented( "Scanning available plugins..." ); $availablePlugins = $this->scanModulesOrPlugins( 'plugins' ); if ( count( $availablePlugins ) === 0 ) { $this->output( 'none' ); } $this->output( "\n" ); if ( count( $bannedPlugins ) ) { $availablePlugins = array_diff( $availablePlugins, $bannedPlugins ); } foreach ( array_chunk( $availablePlugins, 5 ) as $pluginChunk ) { $plugins = implode( ', ', $pluginChunk ); $this->outputIndented( "\t$plugins\n" ); } return $availablePlugins; } /** * @return string[] */ public function scanAvailableModules() { $this->outputIndented( "Scanning available modules..." ); $result = $this->client->request( '_nodes' ); $result = $result->getData(); $availableModules = $this->scanModulesOrPlugins( 'modules' ); if ( count( $availableModules ) === 0 ) { $this->output( 'none' ); } $this->output( "\n" ); foreach ( array_chunk( $availableModules, 5 ) as $moduleChunk ) { $modules = implode( ', ', $moduleChunk ); $this->outputIndented( "\t$modules\n" ); } return $availableModules; } // @todo: bring below options together in some abstract class where Validator & Reindexer also extend from /** * @param string $message * @param mixed $channel */ protected function output( $message, $channel = null ) { if ( $this->out ) { $this->out->output( $message, $channel ); } } /** * @param string $message */ protected function outputIndented( $message ) { if ( $this->out ) { $this->out->outputIndented( $message ); } } /** * @param string $message * @param int $die */ private function error( $message, $die = 0 ) { // @todo: I'll want to get rid of this method, but this patch will be big enough already // @todo: I'll probably want to throw exceptions and/or return Status objects instead, later if ( $this->out ) { $this->out->error( $message, $die ); } $die = intval( $die ); if ( $die > 0 ) { die( $die ); } } /** * Get index health * * @param string $indexName * @return array the index health status */ public function getIndexHealth( $indexName ) { $path = "_cluster/health/$indexName"; $response = $this->client->request( $path ); if ( $response->hasError() ) { throw new \Exception( "Error while fetching index health status: ". $response->getError() ); } return $response->getData(); } /** * Wait for the index to go green * * @param string $indexName * @param int $timeout * @return boolean true if the index is green false otherwise. */ public function waitForGreen( $indexName, $timeout ) { $startTime = time(); while( ( $startTime + $timeout ) > time() ) { try { $response = $this->getIndexHealth( $indexName ); $status = isset ( $response['status'] ) ? $response['status'] : 'unknown'; if ( $status == 'green' ) { $this->outputIndented( "\tGreen!\n" ); return true; } $this->outputIndented( "\tIndex is $status retrying...\n" ); sleep( 5 ); } catch( \Exception $e ) { $this->output( "Error while waiting for green ({$e->getMessage()}), retrying...\n" ); } } return false; } }