/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ambari.server.bootstrap; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.ambari.server.utils.Closeables; import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Runnable class that gets the hoststatus output by looking at the files * in a certain directory. Only meant to be useful for bootstrap as of now. */ class BSHostStatusCollector { private File requestIdDir; private List<BSHostStatus> hostStatus; public static final String logFileFilter = ".log"; public static final String doneFileFilter = ".done"; private static Log LOG = LogFactory.getLog(BSHostStatusCollector.class); private List<String> hosts; public BSHostStatusCollector(File requestIdDir, List<String> hosts) { this.requestIdDir = requestIdDir; this.hosts = hosts; } public List<BSHostStatus> getHostStatus() { return hostStatus; } public void run() { LOG.info("Request directory " + requestIdDir); hostStatus = new ArrayList<>(); if (hosts == null) { return; } File done; File log; LOG.info("HostList for polling on " + hosts); for (String host : hosts) { /* Read through the files and gather output */ BSHostStatus status = new BSHostStatus(); status.setHostName(host); done = new File(requestIdDir, host + doneFileFilter); log = new File(requestIdDir, host + logFileFilter); if (LOG.isDebugEnabled()) { LOG.debug("Polling bootstrap status for host" + ", requestDir=" + requestIdDir + ", host=" + host + ", doneFileExists=" + done.exists() + ", logFileExists=" + log.exists()); } if (!done.exists()) { status.setStatus("RUNNING"); } else { status.setStatus("FAILED"); try { String statusCode = FileUtils.readFileToString(done).trim(); if (statusCode.equals("0")) { status.setStatus("DONE"); } updateStatus(status, statusCode); } catch (IOException e) { LOG.info("Error reading done file " + done); } } if (!log.exists()) { status.setLog(""); } else { String logString = ""; BufferedReader reader = null; try { StringBuilder sb = new StringBuilder(); reader = new BufferedReader(new FileReader(log)); String line = null; while (null != (line = reader.readLine())) { if (line.startsWith("tcgetattr:") || line.startsWith("tput:")) continue; if (0 != sb.length() || 0 == line.length()) sb.append('\n'); if (-1 != line.indexOf ("\\n")) sb.append(line.replace("\\n", "\n")); else sb.append(line); } logString = sb.toString(); } catch (IOException e) { LOG.info("Error reading log file " + log + ". Log file may be have not created yet"); } finally { Closeables.closeSilently(reader); } status.setLog(logString); } hostStatus.add(status); } } private void updateStatus(BSHostStatus status, String statusCode) { status.setStatusCode(statusCode); int reason = -1; try { reason = Integer.parseInt(statusCode); } catch (Exception ignored) { } switch (reason) { // case X: (as we find them) case 2: status.setStatusAction("Processing could not continue because the file was not found."); break; case 255: default: if (null != status.getLog()) { String lowerLog = status.getLog().toLowerCase(); if (-1 != lowerLog.indexOf("permission denied") && -1 != lowerLog.indexOf("publickey")) { status.setStatusAction("Use correct SSH key"); } else if (-1 != lowerLog.indexOf("connect to host")) { status.setStatusAction("Please verify that the hostname '" + status.getHostName() + "' is correct."); } } break; } } }