From d9019b3f701bdd292908e848595b27ab0cc2f96e Mon Sep 17 00:00:00 2001 From: frank Date: Thu, 23 Feb 2012 13:39:55 -0800 Subject: [PATCH] Bug 13962 - CloudRuntimeException: Failed to update keypairs on disk: cannot create key file null/.ssh/id_rsa Changes for Script.java: 1. Even the script is non-timeout one, set default timeout to one hour. This avoid a wrongn script forever hang 2. When InterruptedException happens, check if timeout is really reached, if not, continue status 13962: resolved fixed reviewed-by: Alex, Edison --- .../cloud/server/ConfigurationServerImpl.java | 5 +- utils/src/com/cloud/utils/script/Script.java | 64 ++++++++++++------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 43126b036cc..e65feb74946 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -583,7 +583,10 @@ public class ConfigurationServerImpl implements ConfigurationServer { return; } String already = _configDao.getValue("ssh.privatekey"); - String homeDir = Script.runSimpleBashScript("echo ~"); + String homeDir = Script.runSimpleBashScript("echo ~cloud"); + if (homeDir == null) { + throw new CloudRuntimeException("Cannot get home directory for account: cloud"); + } if (s_logger.isInfoEnabled()) { s_logger.info("Processing updateKeyPairs"); } diff --git a/utils/src/com/cloud/utils/script/Script.java b/utils/src/com/cloud/utils/script/Script.java index ea6fe12f250..91835cb405c 100755 --- a/utils/src/com/cloud/utils/script/Script.java +++ b/utils/src/com/cloud/utils/script/Script.java @@ -47,6 +47,8 @@ public class Script implements Callable { public static final String ERR_EXECUTE = "execute.error"; public static final String ERR_TIMEOUT = "timeout"; + private int _defaultTimeout = 3600 * 1000; /* 1 hour */ + private long _createTime = System.currentTimeMillis(); private boolean _passwordCommand = false; @@ -64,6 +66,10 @@ public class Script implements Callable { _command = new ArrayList(); _command.add(command); _timeout = timeout; + if (_timeout == 0) { + /* always using default timeout 1 hour to avoid thread hang */ + _timeout = _defaultTimeout; + } _process = null; _logger = logger != null ? logger : s_logger; } @@ -111,6 +117,10 @@ public class Script implements Callable { _workDir = workDir; } + private boolean isTimeout() { + return (System.currentTimeMillis() - _timeout) > _createTime; + } + protected String buildCommandLine(String[] command) { StringBuilder builder = new StringBuilder(); boolean obscureParam = false; @@ -193,32 +203,42 @@ public class Script implements Callable { s_executors.execute(task); } - try { - if (_process.waitFor() == 0) { - _logger.debug("Execution is successful."); + while (true) { + try { + if (_process.waitFor() == 0) { + _logger.debug("Execution is successful."); - return interpreter.drain() ? task.getResult() : interpreter.interpret(ir); - } - } catch (InterruptedException e) { - TimedOutLogger log = new TimedOutLogger(_process); - Task timedoutTask = new Task(log, ir); + return interpreter.drain() ? task.getResult() : interpreter.interpret(ir); + } else { + break; + } + } catch (InterruptedException e) { + if (!isTimeout()) { + /* This is not timeout, we are interrupted by others, continue */ + _logger.debug("We are interrupted but it's not a timeout, just continue"); + continue; + } + + TimedOutLogger log = new TimedOutLogger(_process); + Task timedoutTask = new Task(log, ir); - timedoutTask.run(); - if (!_passwordCommand) { - _logger.warn("Timed out: " + buildCommandLine(command) + ". Output is: " + timedoutTask.getResult()); - } else { - _logger.warn("Timed out: " + buildCommandLine(command)); - } + timedoutTask.run(); + if (!_passwordCommand) { + _logger.warn("Timed out: " + buildCommandLine(command) + ". Output is: " + timedoutTask.getResult()); + } else { + _logger.warn("Timed out: " + buildCommandLine(command)); + } - return ERR_TIMEOUT; - } finally { - if (future != null) { - future.cancel(false); - } - Thread.interrupted(); - } + return ERR_TIMEOUT; + } finally { + if (future != null) { + future.cancel(false); + } + Thread.interrupted(); + } + } - _logger.debug("Exit value is " + _process.exitValue()); + _logger.debug("Exit value is " + _process.exitValue()); BufferedReader reader = new BufferedReader(new InputStreamReader(_process.getInputStream()), 128);