summaryrefslogtreecommitdiffstats
path: root/node-maintainer
diff options
context:
space:
mode:
authorvalerijf <valerijf@yahoo-inc.com>2017-03-09 15:11:07 +0100
committervalerijf <valerijf@yahoo-inc.com>2017-03-09 15:11:07 +0100
commit5930e8bc49b4d6314d9cedc6223791f091739717 (patch)
treec5f23cf9a5e7ddcb21a3dfbccd52edf668606d60 /node-maintainer
parent86d966c3e11389b2f4190f7a549528efd6a8f11f (diff)
Removed node-maintainer REST API
Diffstat (limited to 'node-maintainer')
-rw-r--r--node-maintainer/src/main/application/services.xml12
-rw-r--r--node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/Maintainer.java146
-rw-r--r--node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/ErrorResponse.java59
-rw-r--r--node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/MaintainerApiHandler.java219
-rw-r--r--node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/MessageResponse.java33
5 files changed, 140 insertions, 329 deletions
diff --git a/node-maintainer/src/main/application/services.xml b/node-maintainer/src/main/application/services.xml
deleted file mode 100644
index 09effc10ebd..00000000000
--- a/node-maintainer/src/main/application/services.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!-- Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
-<services version="1.0">
- <jdisc version="1.0" jetty="true">
- <http>
- <server id='server1' port='19094' />
- </http>
- <handler id="com.yahoo.vespa.hosted.node.maintainer.restapi.v1.MaintainerApiHandler" bundle="node-maintainer">
- <binding>http://*/maintainer/*</binding>
- </handler>
- </jdisc>
-</services>
diff --git a/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/Maintainer.java b/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/Maintainer.java
index 7a502476e0f..919643f40ee 100644
--- a/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/Maintainer.java
+++ b/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/Maintainer.java
@@ -1,32 +1,166 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.node.maintainer;
-import com.yahoo.container.logging.AccessLog;
import com.yahoo.slime.ArrayTraverser;
import com.yahoo.slime.Inspector;
import com.yahoo.slime.Type;
+import com.yahoo.system.ProcessExecuter;
import com.yahoo.vespa.config.SlimeUtils;
-import com.yahoo.vespa.hosted.node.maintainer.restapi.v1.MaintainerApiHandler;
+import org.apache.http.impl.client.HttpClientBuilder;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
/**
* @author freva
*/
public class Maintainer {
+ private static final CoreCollector coreCollector = new CoreCollector(new ProcessExecuter());
+ private static final CoredumpHandler coredumpHandler = new CoredumpHandler(HttpClientBuilder.create().build(), coreCollector);
+
public static void main(String[] args) {
if (args.length != 1) {
throw new RuntimeException("Expected only 1 argument - a JSON list of maintainer jobs to execute");
}
- MaintainerApiHandler handler = new MaintainerApiHandler(Runnable::run, AccessLog.voidAccessLog());
Inspector object = SlimeUtils.jsonToSlime(args[0].getBytes()).get();
if (object.type() != Type.ARRAY) {
throw new IllegalArgumentException("Expected a list maintainer jobs to execute");
}
object.traverse((ArrayTraverser) (int i, Inspector item) -> {
- String type = handler.getFieldOrFail(item, "type").asString();
- Inspector arguments = handler.getFieldOrFail(item, "arguments");
- handler.parseMaintenanceJob(type, arguments);
+ String type = getFieldOrFail(item, "type").asString();
+ Inspector arguments = getFieldOrFail(item, "arguments");
+ parseMaintenanceJob(type, arguments);
});
}
+
+ private static void parseMaintenanceJob(String type, Inspector arguments) {
+ if (arguments.type() != Type.OBJECT) {
+ throw new IllegalArgumentException("Expected a 'arguments' to be an object");
+ }
+
+ switch (type) {
+ case "delete-files":
+ parseDeleteFilesJob(arguments);
+ break;
+
+ case "delete-directories":
+ parseDeleteDirectoriesJob(arguments);
+ break;
+
+ case "recursive-delete":
+ parseRecursiveDelete(arguments);
+ break;
+
+ case "move-files":
+ parseMoveFiles(arguments);
+ break;
+
+ case "handle-core-dumps":
+ parseHandleCoreDumps(arguments);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown job: " + type);
+ }
+ }
+
+ private static void parseDeleteFilesJob(Inspector arguments) {
+ Path basePath = Paths.get(getFieldOrFail(arguments, "basePath").asString());
+ Duration maxAge = Duration.ofSeconds(getFieldOrFail(arguments, "maxAgeSeconds").asLong());
+ Optional<String> fileNameRegex = SlimeUtils.optionalString(getFieldOrFail(arguments, "fileNameRegex"));
+ boolean recursive = getFieldOrFail(arguments, "recursive").asBool();
+ try {
+ FileHelper.deleteFiles(basePath, maxAge, fileNameRegex, recursive);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed deleting files under " + basePath.toAbsolutePath() +
+ fileNameRegex.map(regex -> ", matching '" + regex + "'").orElse("") +
+ ", " + (recursive ? "" : "not ") + "recursively" +
+ " and older than " + maxAge, e);
+ }
+ }
+
+ private static void parseDeleteDirectoriesJob(Inspector arguments) {
+ Path basePath = Paths.get(getFieldOrFail(arguments, "basePath").asString());
+ Duration maxAge = Duration.ofSeconds(getFieldOrFail(arguments, "maxAgeSeconds").asLong());
+ Optional<String> dirNameRegex = SlimeUtils.optionalString(getFieldOrFail(arguments, "dirNameRegex"));
+ try {
+ FileHelper.deleteDirectories(basePath, maxAge, dirNameRegex);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed deleting directories under " + basePath.toAbsolutePath() +
+ dirNameRegex.map(regex -> ", matching '" + regex + "'").orElse("") +
+ " and older than " + maxAge, e);
+ }
+ }
+
+ private static void parseRecursiveDelete(Inspector arguments) {
+ Path basePath = Paths.get(getFieldOrFail(arguments, "path").asString());
+ try {
+ FileHelper.recursiveDelete(basePath);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed deleting " + basePath.toAbsolutePath(), e);
+ }
+ }
+
+ private static void parseMoveFiles(Inspector arguments) {
+ Path from = Paths.get(getFieldOrFail(arguments, "from").asString());
+ Path to = Paths.get(getFieldOrFail(arguments, "to").asString());
+
+ try {
+ FileHelper.moveIfExists(from, to);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed moving from " + from.toAbsolutePath() + ", to " + to.toAbsolutePath(), e);
+ }
+ }
+
+ private static void parseHandleCoreDumps(Inspector arguments) {
+ Path coredumpsPath = Paths.get(getFieldOrFail(arguments, "coredumpsPath").asString());
+ Path doneCoredumpsPath = Paths.get(getFieldOrFail(arguments, "doneCoredumpsPath").asString());
+ Map<String, Object> attributesMap = parseMap(getFieldOrFail(arguments, "attributes"));
+
+ try {
+ coredumpHandler.removeJavaCoredumps(coredumpsPath);
+ coredumpHandler.processAndReportCoredumps(coredumpsPath, doneCoredumpsPath, attributesMap);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed processing coredumps at " + coredumpsPath.toAbsolutePath() +
+ ", moving fished dumps to " + doneCoredumpsPath.toAbsolutePath(), e);
+ }
+ }
+
+ private static Map<String, Object> parseMap(Inspector object) {
+ Map<String, Object> map = new HashMap<>();
+ getFieldOrFail(object, "attributes").traverse((String key, Inspector value) -> {
+ switch (value.type()) {
+ case BOOL:
+ map.put(key, value.asBool());
+ break;
+ case LONG:
+ map.put(key, value.asLong());
+ break;
+ case DOUBLE:
+ map.put(key, value.asDouble());
+ break;
+ case STRING:
+ map.put(key, value.asString());
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid attribute for key '" + key + "', value " + value);
+ }
+ });
+ return map;
+ }
+
+ private static Inspector getFieldOrFail(Inspector object, String key) {
+ Inspector out = object.field(key);
+ if (out.type() == Type.NIX) {
+ throw new IllegalArgumentException("Key '" + key + "' was not found!");
+ }
+ return out;
+ }
}
diff --git a/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/ErrorResponse.java b/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/ErrorResponse.java
deleted file mode 100644
index 702ef1e43d9..00000000000
--- a/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/ErrorResponse.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.node.maintainer.restapi.v1;
-
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.slime.Cursor;
-import com.yahoo.slime.JsonFormat;
-import com.yahoo.slime.Slime;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import static com.yahoo.jdisc.Response.Status.BAD_REQUEST;
-import static com.yahoo.jdisc.Response.Status.INTERNAL_SERVER_ERROR;
-import static com.yahoo.jdisc.Response.Status.METHOD_NOT_ALLOWED;
-import static com.yahoo.jdisc.Response.Status.NOT_FOUND;
-
-public class ErrorResponse extends HttpResponse {
-
- private final Slime slime = new Slime();
-
- public enum errorCodes {
- NOT_FOUND,
- BAD_REQUEST,
- METHOD_NOT_ALLOWED,
- INTERNAL_SERVER_ERROR
- }
-
- public ErrorResponse(int code, String errorType, String message) {
- super(code);
- Cursor root = slime.setObject();
- root.setString("error-code", errorType);
- root.setString("message", message);
- }
-
- public static ErrorResponse notFoundError(String message) {
- return new ErrorResponse(NOT_FOUND, errorCodes.NOT_FOUND.name(), message);
- }
-
- public static ErrorResponse internalServerError(String message) {
- return new ErrorResponse(INTERNAL_SERVER_ERROR, errorCodes.INTERNAL_SERVER_ERROR.name(), message);
- }
-
- public static ErrorResponse badRequest(String message) {
- return new ErrorResponse(BAD_REQUEST, errorCodes.BAD_REQUEST.name(), message);
- }
-
- public static ErrorResponse methodNotAllowed(String message) {
- return new ErrorResponse(METHOD_NOT_ALLOWED, errorCodes.METHOD_NOT_ALLOWED.name(), message);
- }
-
- @Override
- public void render(OutputStream stream) throws IOException {
- new JsonFormat(true).encode(stream, slime);
- }
-
- @Override
- public String getContentType() { return "application/json"; }
-
-}
diff --git a/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/MaintainerApiHandler.java b/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/MaintainerApiHandler.java
deleted file mode 100644
index 7aa8b09c746..00000000000
--- a/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/MaintainerApiHandler.java
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.node.maintainer.restapi.v1;
-
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.jdisc.LoggingRequestHandler;
-import com.yahoo.container.logging.AccessLog;
-import com.yahoo.io.IOUtils;
-import com.yahoo.slime.ArrayTraverser;
-import com.yahoo.slime.Inspector;
-import com.yahoo.slime.Slime;
-import com.yahoo.slime.Type;
-import com.yahoo.system.ProcessExecuter;
-import com.yahoo.vespa.config.SlimeUtils;
-import com.yahoo.vespa.hosted.node.maintainer.CoreCollector;
-import com.yahoo.vespa.hosted.node.maintainer.CoredumpHandler;
-import com.yahoo.vespa.hosted.node.maintainer.FileHelper;
-import com.yahoo.yolean.Exceptions;
-import org.apache.http.impl.client.HttpClientBuilder;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.Executor;
-import java.util.logging.Level;
-
-
-/**
- * @author freva
- */
-public class MaintainerApiHandler extends LoggingRequestHandler {
- private static final CoreCollector coreCollector = new CoreCollector(new ProcessExecuter());
- private static final CoredumpHandler coredumpHandler = new CoredumpHandler(HttpClientBuilder.create().build(), coreCollector);
-
- public MaintainerApiHandler(Executor executor, AccessLog accessLog) {
- super(executor, accessLog);
- }
-
- @Override
- public HttpResponse handle(HttpRequest request) {
- try {
- switch (request.getMethod()) {
- case POST: return handlePOST(request);
- default: return ErrorResponse.methodNotAllowed("Method '" + request.getMethod() + "' is not supported");
- }
- }
- catch (IllegalArgumentException e) {
- return ErrorResponse.badRequest(Exceptions.toMessageString(e));
- }
- catch (RuntimeException e) {
- log.log(Level.WARNING, "Unexpected error handling '" + request.getUri() + "'", e);
- return ErrorResponse.internalServerError(Exceptions.toMessageString(e));
- }
- }
-
- private HttpResponse handlePOST(HttpRequest request) {
- String requestPath = request.getUri().getPath();
- if (requestPath.equals("/maintainer/v1")) {
- Inspector object = toSlime(request.getData()).get();
- if (object.type() != Type.ARRAY) {
- throw new IllegalArgumentException("Expected a list maintainer jobs to execute");
- }
-
- object.traverse((ArrayTraverser) (int i, Inspector item) -> {
- String type = getFieldOrFail(item, "type").asString();
- Inspector arguments = getFieldOrFail(item, "arguments");
- parseMaintenanceJob(type, arguments);
- });
- return new MessageResponse("Successfully executed " + object.entries() + " commands");
-
- } else if (requestPath.startsWith("/maintainer/v1/")) {
- String type = requestPath.substring(requestPath.lastIndexOf('/') + 1);
- Inspector arguments = toSlime(request.getData()).get();
- parseMaintenanceJob(type, arguments);
- return new MessageResponse("Successfully executed " + type);
-
- } else {
- return ErrorResponse.notFoundError("Nothing at path '" + requestPath + "'");
- }
- }
-
- public void parseMaintenanceJob(String type, Inspector arguments) {
- if (arguments.type() != Type.OBJECT) {
- throw new IllegalArgumentException("Expected a 'arguments' to be an object");
- }
-
- switch (type) {
- case "delete-files":
- parseDeleteFilesJob(arguments);
- break;
-
- case "delete-directories":
- parseDeleteDirectoriesJob(arguments);
- break;
-
- case "recursive-delete":
- parseRecursiveDelete(arguments);
- break;
-
- case "move-files":
- parseMoveFiles(arguments);
- break;
-
- case "handle-core-dumps":
- parseHandleCoreDumps(arguments);
- break;
-
- default:
- throw new IllegalArgumentException("Unknown job: " + type);
- }
- }
-
- private void parseDeleteFilesJob(Inspector arguments) {
- Path basePath = Paths.get(getFieldOrFail(arguments, "basePath").asString());
- Duration maxAge = Duration.ofSeconds(getFieldOrFail(arguments, "maxAgeSeconds").asLong());
- Optional<String> fileNameRegex = SlimeUtils.optionalString(getFieldOrFail(arguments, "fileNameRegex"));
- boolean recursive = getFieldOrFail(arguments, "recursive").asBool();
- try {
- FileHelper.deleteFiles(basePath, maxAge, fileNameRegex, recursive);
- } catch (IOException e) {
- throw new RuntimeException("Failed deleting files under " + basePath.toAbsolutePath() +
- fileNameRegex.map(regex -> ", matching '" + regex + "'").orElse("") +
- ", " + (recursive ? "" : "not ") + "recursively" +
- " and older than " + maxAge, e);
- }
- }
-
- private void parseDeleteDirectoriesJob(Inspector arguments) {
- Path basePath = Paths.get(getFieldOrFail(arguments, "basePath").asString());
- Duration maxAge = Duration.ofSeconds(getFieldOrFail(arguments, "maxAgeSeconds").asLong());
- Optional<String> dirNameRegex = SlimeUtils.optionalString(getFieldOrFail(arguments, "dirNameRegex"));
- try {
- FileHelper.deleteDirectories(basePath, maxAge, dirNameRegex);
- } catch (IOException e) {
- throw new RuntimeException("Failed deleting directories under " + basePath.toAbsolutePath() +
- dirNameRegex.map(regex -> ", matching '" + regex + "'").orElse("") +
- " and older than " + maxAge, e);
- }
- }
-
- private void parseRecursiveDelete(Inspector arguments) {
- Path basePath = Paths.get(getFieldOrFail(arguments, "path").asString());
- try {
- FileHelper.recursiveDelete(basePath);
- } catch (IOException e) {
- throw new RuntimeException("Failed deleting " + basePath.toAbsolutePath(), e);
- }
- }
-
- private void parseMoveFiles(Inspector arguments) {
- Path from = Paths.get(getFieldOrFail(arguments, "from").asString());
- Path to = Paths.get(getFieldOrFail(arguments, "to").asString());
-
- try {
- FileHelper.moveIfExists(from, to);
- } catch (IOException e) {
- throw new RuntimeException("Failed moving from " + from.toAbsolutePath() + ", to " + to.toAbsolutePath(), e);
- }
- }
-
- private void parseHandleCoreDumps(Inspector arguments) {
- Path coredumpsPath = Paths.get(getFieldOrFail(arguments, "coredumpsPath").asString());
- Path doneCoredumpsPath = Paths.get(getFieldOrFail(arguments, "doneCoredumpsPath").asString());
- Map<String, Object> attributesMap = parseMap(getFieldOrFail(arguments, "attributes"));
-
- try {
- coredumpHandler.removeJavaCoredumps(coredumpsPath);
- coredumpHandler.processAndReportCoredumps(coredumpsPath, doneCoredumpsPath, attributesMap);
- } catch (IOException e) {
- throw new RuntimeException("Failed processing coredumps at " + coredumpsPath.toAbsolutePath() +
- ", moving fished dumps to " + doneCoredumpsPath.toAbsolutePath(), e);
- }
- }
-
- private Map<String, Object> parseMap(Inspector object) {
- Map<String, Object> map = new HashMap<>();
- getFieldOrFail(object, "attributes").traverse((String key, Inspector value) -> {
- switch (value.type()) {
- case BOOL:
- map.put(key, value.asBool());
- break;
- case LONG:
- map.put(key, value.asLong());
- break;
- case DOUBLE:
- map.put(key, value.asDouble());
- break;
- case STRING:
- map.put(key, value.asString());
- break;
- default:
- throw new IllegalArgumentException("Invalid attribute for key '" + key + "', value " + value);
- }
- });
- return map;
- }
-
- private Slime toSlime(InputStream jsonStream) {
- try {
- byte[] jsonBytes = IOUtils.readBytes(jsonStream, 1000 * 1000);
- return SlimeUtils.jsonToSlime(jsonBytes);
- } catch (IOException e) {
- throw new RuntimeException();
- }
- }
-
- public Inspector getFieldOrFail(Inspector object, String key) {
- Inspector out = object.field(key);
- if (out.type() == Type.NIX) {
- throw new IllegalArgumentException("Key '" + key + "' was not found!");
- }
- return out;
- }
-}
diff --git a/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/MessageResponse.java b/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/MessageResponse.java
deleted file mode 100644
index 8fb82cd18c9..00000000000
--- a/node-maintainer/src/main/java/com/yahoo/vespa/hosted/node/maintainer/restapi/v1/MessageResponse.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.node.maintainer.restapi.v1;
-
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.slime.JsonFormat;
-import com.yahoo.slime.Slime;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A 200 ok response with a message in JSON
- *
- * @author bratseth
- */
-public class MessageResponse extends HttpResponse {
-
- private final Slime slime = new Slime();
-
- public MessageResponse(String message) {
- super(200);
- slime.setObject().setString("message", message);
- }
-
- @Override
- public void render(OutputStream stream) throws IOException {
- new JsonFormat(true).encode(stream, slime);
- }
-
- @Override
- public String getContentType() { return "application/json"; }
-
-}