Cscott has uploaded a new change for review.
https://gerrit.wikimedia.org/r/177120
Change subject: Add script to allow host decommissioning.
......................................................................
Add script to allow host decommissioning.
Change-Id: I099004f1a98d2fa2ff4e5db1806205f35b195f77
---
M lib/cli.js
M lib/threads/gc.js
A scripts/clear-host-cache.js
3 files changed, 127 insertions(+), 4 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Collection/OfflineContentGenerator
refs/changes/20/177120/1
diff --git a/lib/cli.js b/lib/cli.js
index 539bdfc..9bb6564 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -58,7 +58,7 @@
};
// Set up logging.
-var setupLogging = exports.setupLogging = function( config ) {
+var setupLogging = exports.setupLogging = function( config, forceStdout ) {
var bunyan = require( 'bunyan' );
var mkPrettyStream = function() {
try {
@@ -71,8 +71,16 @@
return { stream: process.stdout };
}
};
+ var checkStdout = function(streams) {
+ if (forceStdout && !streams.some(function(s) {
+ return s.stream === process.stdout;
+ })) {
+ streams.push( mkPrettyStream() );
+ }
+ return streams;
+ };
var streams = (config.logging && Array.isArray(config.logging.streams))
?
- config.logging.streams : [ mkPrettyStream() ];
+ checkStdout(config.logging.streams) : [ mkPrettyStream() ];
var serializers = (config.logging && config.logging.serializers) ||
bunyan.stdSerializers;
var logger = bunyan.createLogger({
diff --git a/lib/threads/gc.js b/lib/threads/gc.js
index 5896e07..cbcbc79 100644
--- a/lib/threads/gc.js
+++ b/lib/threads/gc.js
@@ -81,7 +81,7 @@
redisClient.connect();
}
-function doSingleRun() {
+function doSingleRun( what ) {
redisClient.on( 'closed', function () {
if ( running ) {
console.error( 'Garbage collector connection to redis
died, killing thread.', {
@@ -93,7 +93,7 @@
redisClient.connect();
return new Promise( function( resolve, reject ) {
redisClient.on('opened', function() {
- doGCRun().then( resolve ).catch( reject );
+ Promise.resolve().then(what || doGCRun).then( resolve,
reject );
} );
} );
}
@@ -316,3 +316,6 @@
exports.start = startThread;
exports.stop = stopThread;
exports.singleRun = doSingleRun;
+
+exports.cleanDir = cleanDir;
+exports.cleanJobStatusObjects = cleanJobStatusObjects;
diff --git a/scripts/clear-host-cache.js b/scripts/clear-host-cache.js
new file mode 100755
index 0000000..31abe1e
--- /dev/null
+++ b/scripts/clear-host-cache.js
@@ -0,0 +1,112 @@
+#!/usr/bin/env node
+"use strict";
+
+/**
+ * Collection Extension host decommission script.
+ *
+ * This script will remove all cached job entries which refer to a
+ * specific host, named on the command-line. This is intended for use
+ * when removing a host for maintenance. First, you'd remove the host
+ * from the round-robin DNS name specified in the Collection extension
+ * configuration, so it no longer accepted new jobs. Once the DNS change
+ * propagated and any existing jobs on that host were complete, you
+ * would run something like:
+ * $ sudo -u ocg -g ocg nodejs-ocg scripts/clear-host-cache.js -c
/etc/ocg/mw-ocg-service.js ocg1002
+ * where `ocg1002` is the name of the host you want to decommission.
+ *
+ * If the hostname is omitted, the script will use the name of the
+ * host on which the script is running.
+ *
+ * The script will not remove job status entries for pending jobs
+ * (unless you use the `--force` flag). It will complain on console
+ * if it finds pending jobs, and exit with a non-zero exit code.
+ * In that case, the operator should wait longer (say, 15 minutes)
+ * for the pending job to complete and the user to collect the
+ * results, before re-running the clear-host-cache script.
+ *
+ * @section LICENSE
+ * 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
+ *
+ * @file
+ */
+
+require( 'es6-shim' );
+require( 'prfun' );
+
+var cli = require( '../lib/cli.js' );
+var commander = require( 'commander' );
+var os = require( 'os' );
+
+// parse command-line options (with a possible additional config file override)
+commander
+ .version( cli.version )
+ .usage('[options] <hostname ...>')
+ .option( '-c, --config <path>', 'Path to the local configuration file' )
+ .option( '-f, --force', 'Remove even pending jobs' )
+ .option( '--quiet', "Don't add stdout to configured loggers")
+ .parse( process.argv );
+
+var config = cli.parseConfig( commander.config );
+cli.setupLogging( config, !commander.quiet );
+cli.setupStatsD( config );
+
+var hosts = commander.args.length ? commander.args :
+ [ config.coordinator.hostname || os.hostname() ];
+
+/* === Do the deed ========================================================= */
+var gc = require( '../lib/threads/gc.js' );
+gc.init( config );
+gc.singleRun(function() {
+ var startTime = Date.now();
+ var pending = 0;
+
+ console.info(
+ 'Clearing cache for hosts: %s', hosts.join(', '),
+ { channel: 'gc' }
+ );
+ var hostre = /^https?:\/\/([^:\/]*)/;
+
+ return gc.cleanJobStatusObjects(function(job) {
+ if (!job.host) {
+ return false; /* not picked up yet, keep */
+ }
+ if (!hosts.some(function(h) { return h === job.host; })) {
+ return false; /* not on the specified host(s) */
+ }
+ if (/^(finished|failed)$/.test(job.state)) {
+ return true; /* delete this cache entry */
+ }
+ pending += 1;
+ if (commander.force) {
+ return true; /* force-remove this pending entry */
+ }
+ return false; /* don't remove it, it's still pending */
+ }).spread(function(total, deleted) {
+ console.info(
+ 'Cleared %d (of %d total) entries from cache in %s
seconds',
+ deleted, total, (Date.now() - startTime) / 1000,
+ { channel: 'gc' }
+ );
+ return pending;
+ });
+}).tap( function() {
+ return new Promise(function(resolve) { gc.stop( resolve ); });
+}).then( function(pending) {
+ if (pending) {
+ console.info(' XXX' );
+ process.exit(1);
+ }
+}).done();
--
To view, visit https://gerrit.wikimedia.org/r/177120
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I099004f1a98d2fa2ff4e5db1806205f35b195f77
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Collection/OfflineContentGenerator
Gerrit-Branch: master
Gerrit-Owner: Cscott <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits