Repository: incubator-brooklyn Updated Branches: refs/heads/master 9a1c59a07 -> 54bbe9bac
web app deploy - use temporary file for upload Uploading the file directly to the webapps folder results in autodeploy triggering before the upload is complete. A problem arises when autodeploy triggers in the same second (before) the upload completes - it will fail due to incomplete file, but will not retry because the timestamp of the file won't change. Change deploy to upload to a temporary file and rename it to a .war only when done. This has a few benefits: * The application won't be undeployed at the start of the upload and be down for the duration of the upload * Once the server observers the updated file we can be sure that it read its full content * If the upload fails (timeout, connection reset, full disk...) the old app won't be undeployed. The fix changes the semantics of the deploy method. Previously it always succeeded regardless of the result of the copy operation. Now it will fail if either the copy or the rename operations fail. Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/14ff153a Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/14ff153a Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/14ff153a Branch: refs/heads/master Commit: 14ff153a066b5155349a7ed30718f0dd9b8889a9 Parents: 0ff4216 Author: Svetoslav Neykov <[email protected]> Authored: Mon Mar 30 16:48:29 2015 +0300 Committer: Svetoslav Neykov <[email protected]> Committed: Mon Mar 30 16:48:29 2015 +0300 ---------------------------------------------------------------------- .../entity/webapp/JavaWebAppSshDriver.java | 45 ++++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/14ff153a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSshDriver.java ---------------------------------------------------------------------- diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSshDriver.java b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSshDriver.java index 9916711..da6d62a 100644 --- a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSshDriver.java +++ b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSshDriver.java @@ -27,6 +27,9 @@ import java.util.Set; import brooklyn.entity.basic.Attributes; import brooklyn.entity.java.JavaSoftwareProcessSshDriver; import brooklyn.location.basic.SshMachineLocation; +import brooklyn.util.task.DynamicTasks; +import brooklyn.util.task.Tasks; +import brooklyn.util.task.ssh.SshTasks; import com.google.common.collect.ImmutableList; @@ -146,15 +149,39 @@ public abstract class JavaWebAppSshDriver extends JavaSoftwareProcessSshDriver i * @see JavaWebAppSoftwareProcess#deploy(String, String) for details of how input filenames are handled */ @Override - public String deploy(String url, String targetName) { - String canonicalTargetName = getFilenameContextMapper().convertDeploymentTargetNameToFilename(targetName); - String dest = getDeployDir() + "/" + canonicalTargetName; - log.info("{} deploying {} to {}:{}", new Object[]{entity, url, getHostname(), dest}); - // create a backup - getMachine().execCommands("backing up old war", ImmutableList.of(String.format("mv -f %s %s.bak > /dev/null 2>&1", dest, dest))); //back up old file/directory - int result = copyResource(url, dest); - log.debug("{} deployed {} to {}:{}: result {}", new Object[]{entity, url, getHostname(), dest, result}); - if (result!=0) log.warn("Problem deploying {} to {}:{} for {}: result {}", new Object[]{url, getHostname(), dest, entity, result}); + public String deploy(final String url, final String targetName) { + final String canonicalTargetName = getFilenameContextMapper().convertDeploymentTargetNameToFilename(targetName); + final String dest = getDeployDir() + "/" + canonicalTargetName; + //write to a .tmp so autodeploy is not triggered during upload + final String tmpDest = dest + ".tmp"; + final String msg = String.format("deploying %s to %s:%s", new Object[]{url, getHostname(), dest}); + log.info(entity + " " + msg); + Tasks.setBlockingDetails(msg); + try { + final String copyTaskMsg = String.format("copying %s to %s:%s", new Object[]{url, getHostname(), tmpDest}); + DynamicTasks.queue(copyTaskMsg, new Runnable() { + @Override + public void run() { + int result = copyResource(url, tmpDest); + if (result != 0) { + throw new IllegalStateException("Invalud result " + result + " while " + copyTaskMsg); + } + } + }); + + // create a backup + DynamicTasks.queue(SshTasks.newSshExecTaskFactory(getMachine(), String.format("mv -f %s %s.bak", dest, dest)) + .allowingNonZeroExitCode()); + + //rename temporary upload file to .war to be picked up for deployment + DynamicTasks.queue(SshTasks.newSshExecTaskFactory(getMachine(), String.format("mv -f %s %s", tmpDest, dest)) + .requiringExitCodeZero()); + log.debug("{} deployed {} to {}:{}", new Object[]{entity, url, getHostname(), dest}); + + DynamicTasks.waitForLast(); + } finally { + Tasks.resetBlockingDetails(); + } return getFilenameContextMapper().convertDeploymentTargetNameToContext(canonicalTargetName); }
