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);
     }
     

Reply via email to