/** Creates a new document server */ public DocServer() { super(); /* really should try and get the companion service name from the env * here, but not worth the effort */ JsonServerSyslog templogger = new JsonServerSyslog( DEFAULT_COMPANION_SERVICE_NAME, JsonServerServlet.KB_DEP, JsonServerSyslog.LOG_LEVEL_INFO, false); if (sysLogOut != null) { templogger.changeOutput(sysLogOut); } // getConfig() gets the service name from the env if it exists config = JsonServerServlet.getConfig(DEFAULT_COMPANION_SERVICE_NAME, templogger); String serverName = config.get(CFG_SERVICE_NAME); if (serverName == null || serverName.isEmpty()) { serverName = DEFAULT_SERVICE_NAME; } final String dlog = config.get(CFG_DOCS_LOC); if (dlog == null || dlog.isEmpty()) { docsLoc = defaultDocsLoc; } else { if (!dlog.startsWith("/")) { docsLoc = "/" + dlog; } else { docsLoc = dlog; } } logger = new JsonServerSyslog( serverName, JsonServerServlet.KB_DEP, JsonServerSyslog.LOG_LEVEL_INFO, false); if (sysLogOut != null) { logger.changeOutput(sysLogOut); } }
@Override protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { final RpcInfo rpc = JsonServerSyslog.getCurrentRpcInfo(); rpc.setId(("" + Math.random()).substring(2)); rpc.setIp(JsonServerServlet.getIpAddress(request, config)); rpc.setMethod("GET"); logHeaders(request); String path = request.getPathInfo(); if (path == null) { // e.g. /docs handle404(request, response); return; } if (path.endsWith("/")) { // e.g. /docs/ path = path + "index.html"; } // the path is already normalized by the framework, so no need to // normalize here path = docsLoc + path; final InputStream is = getClass().getResourceAsStream(path); if (is == null) { handle404(request, response); return; } try { final byte[] page = IOUtils.toByteArray(is); response.getOutputStream().write(page); } catch (IOException ioe) { logger.logErr(request.getRequestURI() + " 500 " + request.getHeader(USER_AGENT)); logger.logErr(ioe); response.sendError(500); return; } logger.logInfo(request.getRequestURI() + " 200 " + request.getHeader(USER_AGENT)); }
public int run( String methodName, File inputFile, boolean stdin, String inputJson, File output, String tagVer, boolean verbose, boolean keepTempFiles, String provRefs, String mountPoints) throws Exception { AuthToken auth = AuthService.login(user, password).getToken(); ////////////////////////////////// Loading image name ///////////////////////////////////// CatalogClient client = new CatalogClient(catalogUrl); String moduleName = methodName.split(Pattern.quote("."))[0]; ModuleVersion mv = client.getModuleVersion( new SelectModuleVersion() .withModuleName(moduleName) .withVersion(tagVer) .withIncludeCompilationReport(1L)); if (mv.getDataVersion() != null) throw new IllegalStateException( "Reference data is required for module " + moduleName + ". This feature is not supported for local calls."); String dockerImage = mv.getDockerImgName(); System.out.println("Docker image name recieved from Catalog: " + dockerImage); ////////////////////////////////// Standard files in run_local //////////////////////////// if (!runDir.exists()) runDir.mkdir(); File runLocalSh = new File(runDir, "run_local.sh"); File runDockerSh = new File(runDir, "run_docker.sh"); if (!runLocalSh.exists()) { FileUtils.writeLines( runLocalSh, Arrays.asList( "#!/bin/bash", "sdir=\"$(cd \"$(dirname \"$(readlink -f \"$0\")\")\" && pwd)\"", "callback_url=$1", "cnt_id=$2", "docker_image=$3", "mount_points=$4", "$sdir/run_docker.sh run -v $sdir/workdir:/kb/module/work $mount_points " + "-e \"SDK_CALLBACK_URL=$callback_url\" --name $cnt_id $docker_image async")); ProcessHelper.cmd("chmod", "+x", runLocalSh.getCanonicalPath()).exec(runDir); } if (!runDockerSh.exists()) { FileUtils.writeLines(runDockerSh, Arrays.asList("#!/bin/bash", "docker \"$@\"")); ProcessHelper.cmd("chmod", "+x", runDockerSh.getCanonicalPath()).exec(runDir); } ////////////////////////////////// Temporary files //////////////////////////////////////// StringBuilder mountPointsDocker = new StringBuilder(); if (mountPoints != null) { for (String part : mountPoints.split(Pattern.quote(","))) { String[] fromTo = part.split(Pattern.quote(":")); String to; if (fromTo.length != 2) { if (fromTo.length == 1) { to = "tmp"; } else { throw new IllegalStateException("Unexpected mount point format: " + part); } } else { to = fromTo[1]; } File fromDir = new File(fromTo[0]); if ((!fromDir.exists()) || (!fromDir.isDirectory())) throw new IllegalStateException("Mount point directory doesn't exist: " + fromDir); String from = fromDir.getCanonicalPath(); if (!to.startsWith("/")) to = "/kb/module/work/" + to; if (mountPointsDocker.length() > 0) mountPointsDocker.append(" "); mountPointsDocker.append("-v ").append(from).append(":").append(to); } } File workDir = new File(runDir, "workdir"); if (workDir.exists()) FileUtils.deleteDirectory(workDir); workDir.mkdir(); File subjobsDir = new File(runDir, "subjobs"); if (subjobsDir.exists()) FileUtils.deleteDirectory(subjobsDir); File tokenFile = new File(workDir, "token"); try (FileWriter fw = new FileWriter(tokenFile)) { fw.write(auth.getToken()); } String jobSrvUrl = kbaseEndpoint + "/userandjobstate"; String wsUrl = kbaseEndpoint + "/ws"; String shockUrl = kbaseEndpoint + "/shock-api"; File configPropsFile = new File(workDir, "config.properties"); PrintWriter pw = new PrintWriter(configPropsFile); try { pw.println("[global]"); pw.println("job_service_url = " + jobSrvUrl); pw.println("workspace_url = " + wsUrl); pw.println("shock_url = " + shockUrl); pw.println("kbase_endpoint = " + kbaseEndpoint); } finally { pw.close(); } ////////////////////////////////// Preparing input.json /////////////////////////////////// String jsonString; if (inputFile != null) { jsonString = FileUtils.readFileToString(inputFile); } else if (inputJson != null) { jsonString = inputJson; } else if (stdin) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); IOUtils.copy(System.in, baos); jsonString = new String(baos.toByteArray(), Charset.forName("utf-8")); } else { throw new IllegalStateException("No one input method is used"); } jsonString = jsonString.trim(); if (!jsonString.startsWith("[")) jsonString = "[" + jsonString + "]"; // Wrapping one argument by array if (verbose) System.out.println("Input parameters: " + jsonString); Map<String, Object> rpc = new LinkedHashMap<String, Object>(); rpc.put("version", "1.1"); rpc.put("method", methodName); List<UObject> params = UObject.getMapper().readValue(jsonString, new TypeReference<List<UObject>>() {}); rpc.put("params", params); rpc.put("context", new LinkedHashMap<String, Object>()); UObject.getMapper().writeValue(new File(workDir, "input.json"), rpc); ////////////////////////////////// Starting callback service ////////////////////////////// int callbackPort = NetUtils.findFreePort(); URL callbackUrl = CallbackServer.getCallbackUrl(callbackPort, callbackNetworks); Server jettyServer = null; if (callbackUrl != null) { if (System.getProperty("os.name").startsWith("Windows")) { JsonServerSyslog.setStaticUseSyslog(false); JsonServerSyslog.setStaticMlogFile(new File(workDir, "callback.log").getCanonicalPath()); } CallbackServerConfig cfg = new CallbackServerConfigBuilder( new URL(kbaseEndpoint), callbackUrl, runDir.toPath(), new LineLogger() { @Override public void logNextLine(String line, boolean isError) { if (isError) { System.err.println(line); } else { System.out.println(line); } } }) .build(); Set<String> releaseTags = new TreeSet<String>(); if (mv.getReleaseTags() != null) releaseTags.addAll(mv.getReleaseTags()); String requestedRelease = releaseTags.contains("release") ? "release" : (releaseTags.contains("beta") ? "beta" : "dev"); final ModuleRunVersion runver = new ModuleRunVersion( new URL(mv.getGitUrl()), new ModuleMethod(methodName), mv.getGitCommitHash(), mv.getVersion(), requestedRelease); List<String> inputWsObjects = new ArrayList<String>(); if (provRefs != null) { inputWsObjects.addAll(Arrays.asList(provRefs.split(Pattern.quote(",")))); } JsonServerServlet catalogSrv = new SDKCallbackServer(auth, cfg, runver, params, inputWsObjects); jettyServer = new Server(callbackPort); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); jettyServer.setHandler(context); context.addServlet(new ServletHolder(catalogSrv), "/*"); jettyServer.start(); } else { if (callbackNetworks != null && callbackNetworks.length > 0) { throw new IllegalStateException( "No proper callback IP was found, " + "please check callback_networks parameter in configuration"); } System.out.println( "WARNING: No callback URL was recieved " + "by the job runner. Local callbacks are disabled."); } ////////////////////////////////// Running Docker ///////////////////////////////////////// final String containerName = "local_" + moduleName.toLowerCase() + "_" + System.currentTimeMillis(); try { System.out.println(); int exitCode = ProcessHelper.cmd( "bash", DirUtils.getFilePath(runLocalSh), callbackUrl.toExternalForm(), containerName, dockerImage, mountPointsDocker.toString()) .exec(runDir) .getExitCode(); File outputTmpFile = new File(workDir, "output.json"); if (!outputTmpFile.exists()) throw new IllegalStateException("Output JSON file was not found"); FinishJobParams outObj = UObject.getMapper().readValue(outputTmpFile, FinishJobParams.class); if (outObj.getError() != null || outObj.getResult() == null) { System.out.println(); if (outObj.getError() == null) { System.err.println("Unknown error (no information)"); } else { System.err.println("Error: " + outObj.getError().getMessage()); if (verbose && outObj.getError().getError() != null) { System.err.println("Error details: \n" + outObj.getError().getError()); } } System.out.println(); } else { String outputJson = UObject.getMapper().writeValueAsString(outObj.getResult()); if (output != null) { FileUtils.writeStringToFile(output, outputJson); System.out.println("Output is saved to file: " + output.getCanonicalPath()); } else { System.out.println(); System.out.println("Output returned by the method:"); System.out.println(outputJson); System.out.println(); } } return exitCode; } finally { try { System.out.println("Deleteing docker container..."); ProcessHelper.cmd( "bash", DirUtils.getFilePath(runDockerSh), "rm", "-v", "-f", containerName) .exec(runDir); } catch (Exception ex) { System.out.println("Error deleting container [" + containerName + "]: " + ex.getMessage()); } if (jettyServer != null) { System.out.println("Shutting down callback server..."); jettyServer.stop(); } if (!keepTempFiles) { System.out.println("Deleting temporary files..."); FileUtils.deleteDirectory(workDir); FileUtils.deleteDirectory(subjobsDir); } } }
private void logHeaders(final HttpServletRequest req) { final String xFF = req.getHeader(X_FORWARDED_FOR); if (xFF != null && !xFF.isEmpty()) { logger.logInfo(X_FORWARDED_FOR + ": " + xFF); } }
private void handle404(final HttpServletRequest request, final HttpServletResponse response) throws IOException { logger.logErr(request.getRequestURI() + " 404 " + request.getHeader(USER_AGENT)); response.sendError(404); }