You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by du...@apache.org on 2020/11/10 08:33:45 UTC

[brooklyn-server] branch winrmtaskfactory created (now f058675)

This is an automated email from the ASF dual-hosted git repository.

duncangrant pushed a change to branch winrmtaskfactory
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git.


      at f058675  installTo for winrm supports urls

This branch includes the following new commits:

     new 9fc8476  First draft taskfactory
     new 1d152cf  Better? Outputstream handling
     new f058675  installTo for winrm supports urls

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[brooklyn-server] 01/03: First draft taskfactory

Posted by du...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

duncangrant pushed a commit to branch winrmtaskfactory
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git

commit 9fc84763665e7f343be6bf9d854ef9d7716217a9
Author: Duncan Grant <du...@cloudsoft.io>
AuthorDate: Thu Nov 5 10:15:50 2020 +0000

    First draft taskfactory
---
 .../brooklyn/api/location/MachineLocation.java     | 19 +++++
 .../core/effector/ssh/SshEffectorTasks.java        |  3 +-
 .../brooklyn/location/ssh/SshMachineLocation.java  | 17 +++-
 .../ssh/internal/AbstractSshExecTaskFactory.java   |  3 +-
 .../util/core/task/system/ProcessTaskFactory.java  |  3 +-
 .../util/core/task/system/ProcessTaskStub.java     |  5 +-
 .../internal/AbstractProcessTaskFactory.java       |  3 +-
 .../system/internal/SystemProcessTaskFactory.java  |  3 +-
 .../brooklyn/core/location/SimulatedLocation.java  | 48 ++++++++++-
 pom.xml                                            |  2 +-
 .../location/winrm/PlainWinRMExecTaskFactory.java  | 72 ++++++++++++++++
 .../apache/brooklyn/location/winrm/WinRMTasks.java | 52 ++++++++++++
 .../location/winrm/WinRmMachineLocation.java       | 99 +++++++++++++++++++---
 .../util/core/internal/winrm/WinRmTool.java        |  2 +-
 .../core/internal/winrm/winrm4j/Winrm4jTool.java   | 14 ++-
 15 files changed, 317 insertions(+), 28 deletions(-)

diff --git a/api/src/main/java/org/apache/brooklyn/api/location/MachineLocation.java b/api/src/main/java/org/apache/brooklyn/api/location/MachineLocation.java
index aa8ef9c..508c5d4 100644
--- a/api/src/main/java/org/apache/brooklyn/api/location/MachineLocation.java
+++ b/api/src/main/java/org/apache/brooklyn/api/location/MachineLocation.java
@@ -19,6 +19,8 @@
 package org.apache.brooklyn.api.location;
 
 import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.brooklyn.util.net.HasNetworkAddresses;
 
@@ -44,4 +46,21 @@ public interface MachineLocation extends AddressableLocation, HasNetworkAddresse
      */
     MachineDetails getMachineDetails();
 
+    String getUser();
+
+    int execCommands(String summaryForLogging, List<String> commands);
+
+    int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands);
+
+    int execCommands(String summaryForLogging, List<String> commands, Map<String, ?> env);
+
+    int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env);
+
+    int execScript(String summaryForLogging, List<String> commands);
+
+    int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands);
+
+    int execScript(String summaryForLogging, List<String> commands, Map<String, ?> env);
+
+    int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env);
 }
diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java
index e285817..706ea3d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java
+++ b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java
@@ -27,6 +27,7 @@ import javax.annotation.Nullable;
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.MachineLocation;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.StringConfigMap;
@@ -105,7 +106,7 @@ public class SshEffectorTasks {
         public SshEffectorTaskFactory(String ...commands) {
             super(commands);
         }
-        public SshEffectorTaskFactory(SshMachineLocation machine, String ...commands) {
+        public SshEffectorTaskFactory(MachineLocation machine, String ...commands) {
             super(machine, commands);
         }
         @Override
diff --git a/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java b/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java
index ada35d0..14df87d 100644
--- a/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java
@@ -514,6 +514,7 @@ public class SshMachineLocation extends AbstractMachineLocation implements Machi
         return HostAndPort.fromParts(host, port);
     }
 
+    @Override
     public String getUser() {
         if (!groovyTruth(user)) {
             if (config().getLocalRaw(SshTool.PROP_USER).isPresent()) {
@@ -698,16 +699,20 @@ public class SshMachineLocation extends AbstractMachineLocation implements Machi
      * and/or {@code commandPrepend} and {@code commandAppend} similar to
      * (currently supported in SshjTool) {@code separator}.)
      */
+    @Override
     public int execCommands(String summaryForLogging, List<String> commands) {
         return execCommands(MutableMap.<String,Object>of(), summaryForLogging, commands, MutableMap.<String,Object>of());
     }
-    public int execCommands(Map<String,?> props, String summaryForLogging, List<String> commands) {
+    @Override
+    public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands) {
         return execCommands(props, summaryForLogging, commands, MutableMap.<String,Object>of());
     }
-    public int execCommands(String summaryForLogging, List<String> commands, Map<String,?> env) {
+    @Override
+    public int execCommands(String summaryForLogging, List<String> commands, Map<String, ?> env) {
         return execCommands(MutableMap.<String,Object>of(), summaryForLogging, commands, env);
     }
-    public int execCommands(Map<String,?> props, String summaryForLogging, List<String> commands, Map<String,?> env) {
+    @Override
+    public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env) {
         return newExecWithLoggingHelpers().execCommands(augmentPropertiesWithSshConfigGivenToProps(props), summaryForLogging, commands, env);
     }
 
@@ -718,15 +723,19 @@ public class SshMachineLocation extends AbstractMachineLocation implements Machi
      * flags 'noStdoutLogging' and 'noStderrLogging' are set. To set a logging prefix, use
      * the flag 'logPrefix'.
      */
+    @Override
     public int execScript(String summaryForLogging, List<String> commands) {
         return execScript(MutableMap.<String,Object>of(), summaryForLogging, commands, MutableMap.<String,Object>of());
     }
+    @Override
     public int execScript(Map<String,?> props, String summaryForLogging, List<String> commands) {
         return execScript(props, summaryForLogging, commands, MutableMap.<String,Object>of());
     }
+    @Override
     public int execScript(String summaryForLogging, List<String> commands, Map<String,?> env) {
         return execScript(MutableMap.<String,Object>of(), summaryForLogging, commands, env);
     }
+    @Override
     public int execScript(Map<String,?> props, String summaryForLogging, List<String> commands, Map<String,?> env) {
         return newExecWithLoggingHelpers().execScript(augmentPropertiesWithSshConfigGivenToProps(props), summaryForLogging, commands, env);
     }
@@ -869,7 +878,7 @@ public class SshMachineLocation extends AbstractMachineLocation implements Machi
             PipedInputStream insO = new PipedInputStream(); OutputStream outO = new PipedOutputStream(insO);
             PipedInputStream insE = new PipedInputStream(); OutputStream outE = new PipedOutputStream(insE);
             StreamGobbler sgsO = new StreamGobbler(insO, null, LOG); sgsO.setLogPrefix("[curl @ "+address+":stdout] ").start();
-            StreamGobbler sgsE = new StreamGobbler(insE, null, LOG); sgsE.setLogPrefix("[curl @ "+address+":stdout] ").start();
+            StreamGobbler sgsE = new StreamGobbler(insE, null, LOG); sgsE.setLogPrefix("[curl @ "+address+":stderr] ").start();
             Map<String, ?> sshProps = MutableMap.<String, Object>builder().putAll(props).put("out", outO).put("err", outE).build();
             int result = execScript(sshProps, "copying remote resource "+url+" to server",  ImmutableList.of(
                     BashCommands.INSTALL_CURL, // TODO should hold the 'installing' mutex
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/ssh/internal/AbstractSshExecTaskFactory.java b/core/src/main/java/org/apache/brooklyn/util/core/task/ssh/internal/AbstractSshExecTaskFactory.java
index 04272e8..354a2bb 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/ssh/internal/AbstractSshExecTaskFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/ssh/internal/AbstractSshExecTaskFactory.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.util.core.task.ssh.internal;
 
 import com.google.common.base.Preconditions;
 
+import org.apache.brooklyn.api.location.MachineLocation;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory;
@@ -35,7 +36,7 @@ public abstract class AbstractSshExecTaskFactory<T extends AbstractProcessTaskFa
     }
 
     /** convenience constructor to supply machine immediately */
-    public AbstractSshExecTaskFactory(SshMachineLocation machine, String ...commands) {
+    public AbstractSshExecTaskFactory(MachineLocation machine, String ...commands) {
         this(commands);
         machine(machine);
     }
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/system/ProcessTaskFactory.java b/core/src/main/java/org/apache/brooklyn/util/core/task/system/ProcessTaskFactory.java
index 8042cc2..b0878c3 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/system/ProcessTaskFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/system/ProcessTaskFactory.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.util.core.task.system;
 
 import java.util.Map;
 
+import org.apache.brooklyn.api.location.MachineLocation;
 import org.apache.brooklyn.api.mgmt.TaskFactory;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
@@ -30,7 +31,7 @@ import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 
 public interface ProcessTaskFactory<T> extends TaskFactory<ProcessTaskWrapper<T>> {
-    public ProcessTaskFactory<T> machine(SshMachineLocation machine);
+    public ProcessTaskFactory<T> machine(MachineLocation machine);
     public ProcessTaskFactory<T> add(String ...commandsToAdd);
     public ProcessTaskFactory<T> add(Iterable<String> commandsToAdd);
     public ProcessTaskFactory<T> requiringExitCodeZero();
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/system/ProcessTaskStub.java b/core/src/main/java/org/apache/brooklyn/util/core/task/system/ProcessTaskStub.java
index 5514ccf..549ba91 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/system/ProcessTaskStub.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/system/ProcessTaskStub.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.brooklyn.api.location.MachineLocation;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.config.ConfigBag;
@@ -35,7 +36,7 @@ public class ProcessTaskStub {
     
     protected final List<String> commands = new ArrayList<String>();
     /** null for localhost */
-    protected SshMachineLocation machine;
+    protected MachineLocation machine;
     
     // config data
     protected String summary;
@@ -75,7 +76,7 @@ public class ProcessTaskStub {
     }
     
     /** null for localhost */
-    public SshMachineLocation getMachine() {
+    public MachineLocation getMachine() {
         return machine;
     }
     
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/system/internal/AbstractProcessTaskFactory.java b/core/src/main/java/org/apache/brooklyn/util/core/task/system/internal/AbstractProcessTaskFactory.java
index 6f9f0e0..e0a225a 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/system/internal/AbstractProcessTaskFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/system/internal/AbstractProcessTaskFactory.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.util.core.task.system.internal;
 import java.util.Arrays;
 import java.util.Map;
 
+import org.apache.brooklyn.api.location.MachineLocation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.config.ConfigKey;
@@ -68,7 +69,7 @@ public abstract class AbstractProcessTaskFactory<T extends AbstractProcessTaskFa
     }
     
     @Override
-    public T machine(SshMachineLocation machine) {
+    public T machine(MachineLocation machine) {
         markDirty();
         this.machine = machine;
         return self();
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/system/internal/SystemProcessTaskFactory.java b/core/src/main/java/org/apache/brooklyn/util/core/task/system/internal/SystemProcessTaskFactory.java
index 20e6180..afe5d33 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/system/internal/SystemProcessTaskFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/system/internal/SystemProcessTaskFactory.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.util.core.task.system.internal;
 
 import java.io.File;
 
+import org.apache.brooklyn.api.location.MachineLocation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.core.config.Sanitizer;
@@ -57,7 +58,7 @@ public class SystemProcessTaskFactory<T extends SystemProcessTaskFactory<T,RET>,
     }
     
     @Override
-    public T machine(SshMachineLocation machine) {
+    public T machine(MachineLocation machine) {
         log.warn("Not permitted to set machines on "+this+" (ignoring - "+machine+")");
         if (log.isDebugEnabled())
             log.debug("Source of attempt to set machines on "+this+" ("+machine+")",
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java b/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
index c5c2c85..41be3f5 100644
--- a/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
+++ b/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.core.location;
 
 import java.net.InetAddress;
 import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -162,7 +163,52 @@ public class SimulatedLocation extends AbstractLocation implements MachineProvis
         OsDetails osDetails = BasicOsDetails.Factory.ANONYMOUS_LINUX;
         return new BasicMachineDetails(hardwareDetails, osDetails);
     }
-    
+
+    @Override
+    public String getUser() {
+        return null;
+    }
+
+    @Override
+    public int execCommands(String summaryForLogging, List<String> commands) {
+        return 0;
+    }
+
+    @Override
+    public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands) {
+        return 0;
+    }
+
+    @Override
+    public int execCommands(String summaryForLogging, List<String> commands, Map<String, ?> env) {
+        return 0;
+    }
+
+    @Override
+    public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env) {
+        return 0;
+    }
+
+    @Override
+    public int execScript(String summaryForLogging, List<String> commands) {
+        return 0;
+    }
+
+    @Override
+    public int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands) {
+        return 0;
+    }
+
+    @Override
+    public int execScript(String summaryForLogging, List<String> commands, Map<String, ?> env) {
+        return 0;
+    }
+
+    @Override
+    public int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env) {
+        return 0;
+    }
+
     private RuntimeException newException(String msg) {
         try {
             Exception result = getConfig(EXCEPTION_CLAZZ).getConstructor(String.class).newInstance(msg);
diff --git a/pom.xml b/pom.xml
index 0e96278..1c56a1a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -164,7 +164,7 @@
         <jax-rs-api.version>2.1.1</jax-rs-api.version> <!-- differs from jclouds 2.1.2, which depends on v2.0.1 -->
         <maxmind.version>2.8.0-rc1</maxmind.version>
         <maxmind-db.version>1.2.1</maxmind-db.version>
-        <winrm4j.version>0.9.0</winrm4j.version> <!--  FIXME NO CHECK IN -->
+        <winrm4j.version>0.9.0-SNAPSHOT</winrm4j.version> <!--  FIXME NO CHECK IN -->
         <felix-osgi-compendium.version>1.4.0</felix-osgi-compendium.version>
         <kubernetes-client.version>4.9.0</kubernetes-client.version>
 
diff --git a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/PlainWinRMExecTaskFactory.java b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/PlainWinRMExecTaskFactory.java
new file mode 100644
index 0000000..0fa344e
--- /dev/null
+++ b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/PlainWinRMExecTaskFactory.java
@@ -0,0 +1,72 @@
+/*
+ * 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.brooklyn.location.winrm;
+
+import com.google.common.base.Function;
+import org.apache.brooklyn.util.core.task.ssh.internal.AbstractSshExecTaskFactory;
+import org.apache.brooklyn.util.core.task.ssh.internal.PlainSshExecTaskFactory;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+
+import java.util.List;
+
+public class PlainWinRMExecTaskFactory<RET> extends AbstractSshExecTaskFactory<PlainSshExecTaskFactory<RET>,RET> {
+
+    /** constructor where machine will be added later */
+    public PlainWinRMExecTaskFactory(String ...commands) {
+        super(commands);
+    }
+
+    /** convenience constructor to supply machine immediately */
+    public PlainWinRMExecTaskFactory(WinRmMachineLocation machine, String ...commands) {
+        this(commands);
+        machine(machine);
+    }
+
+    /** Constructor where machine will be added later */
+    public PlainWinRMExecTaskFactory(List<String> commands) {
+        this(commands.toArray(new String[commands.size()]));
+    }
+
+    /** Convenience constructor to supply machine immediately */
+    public PlainWinRMExecTaskFactory(WinRmMachineLocation machine, List<String> commands) {
+        this(machine, commands.toArray(new String[commands.size()]));
+    }
+
+    @Override
+    public <T2> PlainWinRMExecTaskFactory<T2> returning(ScriptReturnType type) {
+        return (PlainWinRMExecTaskFactory<T2>) super.<T2>returning(type);
+    }
+
+    @Override
+    public <RET2> PlainWinRMExecTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) {
+        return (PlainWinRMExecTaskFactory<RET2>) super.returning(resultTransformation);
+    }
+
+    @Override
+    public PlainWinRMExecTaskFactory<Boolean> returningIsExitCodeZero() {
+        return (PlainWinRMExecTaskFactory<Boolean>) super.returningIsExitCodeZero();
+    }
+
+    @Override
+    public PlainWinRMExecTaskFactory<String> requiringZeroAndReturningStdout() {
+        return (PlainWinRMExecTaskFactory<String>) super.requiringZeroAndReturningStdout();
+    }
+}
+
+
diff --git a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRMTasks.java b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRMTasks.java
new file mode 100644
index 0000000..fb89ad5
--- /dev/null
+++ b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRMTasks.java
@@ -0,0 +1,52 @@
+/*
+ * 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.brooklyn.location.winrm;
+
+import org.apache.brooklyn.api.mgmt.TaskAdaptable;
+import org.apache.brooklyn.api.mgmt.TaskFactory;
+import org.apache.brooklyn.location.winrm.PlainWinRMExecTaskFactory;
+import org.apache.brooklyn.location.winrm.WinRmMachineLocation;
+import org.apache.brooklyn.util.core.ResourceUtils;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory;
+import org.apache.brooklyn.util.net.Urls;
+
+import java.util.Map;
+
+public class WinRMTasks {
+    public static ProcessTaskFactory<Integer> newWinrmExecTaskFactory(org.apache.brooklyn.location.winrm.WinRmMachineLocation winRmMachineLocation, String ...commands) {
+        return new PlainWinRMExecTaskFactory<>(winRmMachineLocation, commands);
+    }
+
+    public static TaskFactory<?> installFromUrl(final ResourceUtils utils, final Map<String, ?> props, final WinRmMachineLocation location, final String url, final String destPath) {
+        return new TaskFactory<TaskAdaptable<?>>() {
+            @Override
+            public TaskAdaptable<?> newTask() {
+                return Tasks.<Void>builder().displayName("installing "+ Urls.getBasename(url)).description("installing "+url+" to "+destPath).body(new Runnable() {
+                    @Override
+                    public void run() {
+                        int result = location.installTo(utils, props, url, destPath);
+                        if (result!=0)
+                            throw new IllegalStateException("Failed to install '"+url+"' to '"+destPath+"' at "+location+": exit code "+result);
+                    }
+                }).build();
+            }
+        };
+    }
+}
diff --git a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java
index 0fd93b7..88d29a0 100644
--- a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java
+++ b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java
@@ -21,10 +21,7 @@ package org.apache.brooklyn.location.winrm;
 import static org.apache.brooklyn.core.config.ConfigKeys.newConfigKeyWithPrefix;
 import static org.apache.brooklyn.core.config.ConfigKeys.newStringConfigKey;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
+import java.io.*;
 import java.net.InetAddress;
 import java.util.List;
 import java.util.Map;
@@ -32,6 +29,7 @@ import java.util.Set;
 
 import javax.annotation.Nullable;
 
+import com.google.common.base.*;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.location.MachineDetails;
 import org.apache.brooklyn.api.location.MachineLocation;
@@ -41,24 +39,25 @@ import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.config.ConfigUtils;
 import org.apache.brooklyn.core.config.Sanitizer;
-import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks;
 import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
 import org.apache.brooklyn.core.location.AbstractMachineLocation;
 import org.apache.brooklyn.core.location.access.PortForwardManager;
 import org.apache.brooklyn.core.location.access.PortForwardManagerLocationResolver;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
 import org.apache.brooklyn.location.ssh.CanResolveOnBoxDir;
+import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ClassLoaderUtils;
+import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.internal.ssh.ShellTool;
 import org.apache.brooklyn.util.core.internal.ssh.SshTool;
 import org.apache.brooklyn.util.core.internal.winrm.WinRmTool;
 import org.apache.brooklyn.util.core.internal.winrm.WinRmToolResponse;
 import org.apache.brooklyn.util.core.internal.winrm.winrm4j.Winrm4jTool;
-import org.apache.brooklyn.util.core.task.DynamicTasks;
-import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
-import org.apache.brooklyn.util.ssh.BashCommands;
+import org.apache.brooklyn.util.stream.StreamGobbler;
 import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.commons.codec.binary.Base64;
@@ -66,10 +65,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.Charsets;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -204,11 +199,54 @@ public class WinRmMachineLocation extends AbstractMachineLocation implements Mac
         return UNKNOWN_MACHINE_DETAILS;
     }
 
+    @Override
     public String getUser() {
         return config().get(USER);
     }
 
     @Override
+    public int execCommands(String summaryForLogging, List<String> commands) {
+        return executeCommand(commands).getStatusCode();
+    }
+
+    @Override
+    public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands) {
+        return executeCommand(props, commands).getStatusCode();
+    }
+
+    @Override
+    public int execCommands(String summaryForLogging, List<String> commands, Map<String, ?> env) {
+        return executeCommand(ImmutableMap.of(Winrm4jTool.ENVIRONMENT, env),commands).getStatusCode();
+    }
+
+    @Override
+    public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env) {
+        ImmutableMap<Object, Object> properties = ImmutableMap.builder().putAll(props).put(Winrm4jTool.ENVIRONMENT, env).build();
+        return executeCommand(properties, commands).getStatusCode();
+    }
+
+    @Override
+    public int execScript(String summaryForLogging, List<String> commands) {
+        return executePsScript(commands).getStatusCode();
+    }
+
+    @Override
+    public int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands) {
+        return executePsScript(props, commands).getStatusCode();
+    }
+
+    @Override
+    public int execScript(String summaryForLogging, List<String> commands, Map<String, ?> env) {
+        return executePsScript(ImmutableMap.of(Winrm4jTool.ENVIRONMENT,env), commands).getStatusCode();
+    }
+
+    @Override
+    public int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env) {
+        ImmutableMap<Object, Object> properties = ImmutableMap.builder().putAll(props).put(Winrm4jTool.ENVIRONMENT, env).build();
+        return executePsScript(properties, commands).getStatusCode();
+    }
+
+    @Override
     public InetAddress getAddress() {
         return getConfig(ADDRESS);
     }
@@ -507,4 +545,41 @@ public class WinRmMachineLocation extends AbstractMachineLocation implements Mac
         return unresolvedPath.replaceAll("/", "\\");
     }
 
+    public int installTo(ResourceUtils utils, Map<String, ?> props, String url, String destPath) {
+        LOG.debug("installing {} to {} on {}, attempting remote curl", new Object[] { url, destPath, this });
+
+        try(PipedInputStream insO = new PipedInputStream(); OutputStream outO = new PipedOutputStream(insO);
+            PipedInputStream insE = new PipedInputStream(); OutputStream outE = new PipedOutputStream(insE);
+            StreamGobbler sgsO = new StreamGobbler(insO, null, LOG);
+            StreamGobbler sgsE = new StreamGobbler(insE, null, LOG)
+            ){
+            sgsO.setLogPrefix("[curl @ "+getAddress()+":stdout] ").start();
+            sgsE.setLogPrefix("[curl @ "+getAddress()+":stderr] ").start();
+            Map<String, ?> winrmProps = MutableMap.<String, Object>builder().putAll(props).put("out", outO).put("err", outE).build();
+            int result = execScript(winrmProps,"",ImmutableList.of(
+                    "$WebClient = New-Object System.Net.WebClient",
+                    "$WebClient.DownloadFile(" + url + "," + destPath + ")"
+            ));
+
+            if (result != 0) {
+                LOG.debug("installing {} to {} on {}, curl failed, attempting local fetch and copy", new Object[] { url, destPath, this });
+                try {
+                    Tasks.setBlockingDetails("retrieving resource "+url+" for copying across");
+                    InputStream stream = utils.getResourceFromUrl(url);
+                    Tasks.setBlockingDetails("copying resource "+url+" to server");
+                    result = copyTo(props, stream, destPath);
+                } finally {
+                    Tasks.setBlockingDetails(null);
+                }
+            }
+            if (result == 0) {
+                LOG.debug("installing {} complete; {} on {}", new Object[] { url, destPath, this });
+            } else {
+                LOG.warn("installing {} failed; {} on {}: {}", new Object[] { url, destPath, this, result });
+            }
+            return result;
+        } catch (IOException e) {
+            throw Throwables.propagate(e);
+        }
+    }
 }
diff --git a/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/WinRmTool.java b/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/WinRmTool.java
index 1d9d2b9..b566224 100644
--- a/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/WinRmTool.java
+++ b/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/WinRmTool.java
@@ -105,6 +105,6 @@ public interface WinRmTool {
     WinRmToolResponse executeCommand(List<String> commands);
 
     WinRmToolResponse executePs(List<String> commands);
-    
+
     WinRmToolResponse copyToServer(InputStream source, String destination);
 }
diff --git a/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java b/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java
index b7ff665..332b008 100644
--- a/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java
+++ b/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java
@@ -20,7 +20,7 @@ package org.apache.brooklyn.util.core.internal.winrm.winrm4j;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import java.io.InputStream;
+import java.io.*;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
@@ -34,6 +34,7 @@ import org.apache.brooklyn.core.internal.BrooklynProperties;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.internal.ssh.ShellTool;
 import org.apache.brooklyn.util.core.internal.winrm.WinRmException;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.javalang.Threads;
@@ -116,7 +117,16 @@ public class Winrm4jTool implements org.apache.brooklyn.util.core.internal.winrm
     public org.apache.brooklyn.util.core.internal.winrm.WinRmToolResponse executeCommand(final List<String> commands) {
         return exec(new Function<io.cloudsoft.winrm4j.winrm.WinRmTool, io.cloudsoft.winrm4j.winrm.WinRmToolResponse>() {
             @Override public WinRmToolResponse apply(io.cloudsoft.winrm4j.winrm.WinRmTool tool) {
-                return tool.executeCommand(commands);
+                OutputStream outputStream = bag.get(ShellTool.PROP_OUT_STREAM);
+                OutputStream errorStream = bag.get(ShellTool.PROP_ERR_STREAM);
+                try(Writer out = outputStream != null ? new OutputStreamWriter(outputStream): new StringWriter();
+                Writer err = errorStream != null ? new OutputStreamWriter(errorStream): new StringWriter()) {
+                    return tool.executeCommand(commands, out, err);
+                } catch (IOException e) {
+                    // TODO Duncan
+                    e.printStackTrace();
+                    return null;
+                }
             }
         });
     }


[brooklyn-server] 02/03: Better? Outputstream handling

Posted by du...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

duncangrant pushed a commit to branch winrmtaskfactory
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git

commit 1d152cfb2c045cef76b17e9ca76eac787de7e780
Author: Duncan Grant <du...@cloudsoft.io>
AuthorDate: Mon Nov 9 09:54:09 2020 +0000

    Better? Outputstream handling
---
 .../apache/brooklyn/location/winrm/WinRmMachineLocation.java   | 10 ++++++----
 .../brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java |  6 +++++-
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java
index 88d29a0..1198697 100644
--- a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java
+++ b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java
@@ -556,10 +556,12 @@ public class WinRmMachineLocation extends AbstractMachineLocation implements Mac
             sgsO.setLogPrefix("[curl @ "+getAddress()+":stdout] ").start();
             sgsE.setLogPrefix("[curl @ "+getAddress()+":stderr] ").start();
             Map<String, ?> winrmProps = MutableMap.<String, Object>builder().putAll(props).put("out", outO).put("err", outE).build();
-            int result = execScript(winrmProps,"",ImmutableList.of(
-                    "$WebClient = New-Object System.Net.WebClient",
-                    "$WebClient.DownloadFile(" + url + "," + destPath + ")"
-            ));
+//            int result = execScript(winrmProps,"",ImmutableList.of(
+//                    "$WebClient = New-Object System.Net.WebClient",
+//                    "$WebClient.DownloadFile(" + url + "," + destPath + ")"
+//            ));
+
+            int result = 1;
 
             if (result != 0) {
                 LOG.debug("installing {} to {} on {}, curl failed, attempting local fetch and copy", new Object[] { url, destPath, this });
diff --git a/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java b/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java
index 332b008..784e7d1 100644
--- a/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java
+++ b/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java
@@ -141,7 +141,11 @@ public class Winrm4jTool implements org.apache.brooklyn.util.core.internal.winrm
     public org.apache.brooklyn.util.core.internal.winrm.WinRmToolResponse executePs(final List<String> commands) {
         return exec(new Function<io.cloudsoft.winrm4j.winrm.WinRmTool, io.cloudsoft.winrm4j.winrm.WinRmToolResponse>() {
             @Override public WinRmToolResponse apply(io.cloudsoft.winrm4j.winrm.WinRmTool tool) {
-                return tool.executePs(commands);
+                OutputStream outputStream = bag.get(ShellTool.PROP_OUT_STREAM);
+                OutputStream errorStream = bag.get(ShellTool.PROP_ERR_STREAM);
+                Writer out = outputStream != null ? new OutputStreamWriter(outputStream): new StringWriter();
+                Writer err = errorStream != null ? new OutputStreamWriter(errorStream): new StringWriter();
+                return tool.executePs(commands, out, err);
             }
         });
     }


[brooklyn-server] 03/03: installTo for winrm supports urls

Posted by du...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

duncangrant pushed a commit to branch winrmtaskfactory
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git

commit f0586759c5099d93f07611319d71c26fe71ea190
Author: Duncan Grant <du...@cloudsoft.io>
AuthorDate: Tue Nov 10 08:19:49 2020 +0000

    installTo for winrm supports urls
---
 .../brooklyn/api/location/MachineLocation.java     | 12 ------
 .../brooklyn/location/ssh/SshMachineLocation.java  |  6 ---
 .../brooklyn/core/location/SimulatedLocation.java  | 30 ---------------
 .../location/winrm/WinRmMachineLocation.java       | 42 +++-----------------
 .../core/internal/winrm/winrm4j/Winrm4jTool.java   | 45 +++++++++-------------
 5 files changed, 24 insertions(+), 111 deletions(-)

diff --git a/api/src/main/java/org/apache/brooklyn/api/location/MachineLocation.java b/api/src/main/java/org/apache/brooklyn/api/location/MachineLocation.java
index 508c5d4..d207886 100644
--- a/api/src/main/java/org/apache/brooklyn/api/location/MachineLocation.java
+++ b/api/src/main/java/org/apache/brooklyn/api/location/MachineLocation.java
@@ -48,19 +48,7 @@ public interface MachineLocation extends AddressableLocation, HasNetworkAddresse
 
     String getUser();
 
-    int execCommands(String summaryForLogging, List<String> commands);
-
-    int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands);
-
-    int execCommands(String summaryForLogging, List<String> commands, Map<String, ?> env);
-
     int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env);
 
-    int execScript(String summaryForLogging, List<String> commands);
-
-    int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands);
-
-    int execScript(String summaryForLogging, List<String> commands, Map<String, ?> env);
-
     int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env);
 }
diff --git a/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java b/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java
index 14df87d..d5ed481 100644
--- a/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/ssh/SshMachineLocation.java
@@ -699,15 +699,12 @@ public class SshMachineLocation extends AbstractMachineLocation implements Machi
      * and/or {@code commandPrepend} and {@code commandAppend} similar to
      * (currently supported in SshjTool) {@code separator}.)
      */
-    @Override
     public int execCommands(String summaryForLogging, List<String> commands) {
         return execCommands(MutableMap.<String,Object>of(), summaryForLogging, commands, MutableMap.<String,Object>of());
     }
-    @Override
     public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands) {
         return execCommands(props, summaryForLogging, commands, MutableMap.<String,Object>of());
     }
-    @Override
     public int execCommands(String summaryForLogging, List<String> commands, Map<String, ?> env) {
         return execCommands(MutableMap.<String,Object>of(), summaryForLogging, commands, env);
     }
@@ -723,15 +720,12 @@ public class SshMachineLocation extends AbstractMachineLocation implements Machi
      * flags 'noStdoutLogging' and 'noStderrLogging' are set. To set a logging prefix, use
      * the flag 'logPrefix'.
      */
-    @Override
     public int execScript(String summaryForLogging, List<String> commands) {
         return execScript(MutableMap.<String,Object>of(), summaryForLogging, commands, MutableMap.<String,Object>of());
     }
-    @Override
     public int execScript(Map<String,?> props, String summaryForLogging, List<String> commands) {
         return execScript(props, summaryForLogging, commands, MutableMap.<String,Object>of());
     }
-    @Override
     public int execScript(String summaryForLogging, List<String> commands, Map<String,?> env) {
         return execScript(MutableMap.<String,Object>of(), summaryForLogging, commands, env);
     }
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java b/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
index 41be3f5..83faa97 100644
--- a/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
+++ b/core/src/test/java/org/apache/brooklyn/core/location/SimulatedLocation.java
@@ -170,41 +170,11 @@ public class SimulatedLocation extends AbstractLocation implements MachineProvis
     }
 
     @Override
-    public int execCommands(String summaryForLogging, List<String> commands) {
-        return 0;
-    }
-
-    @Override
-    public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands) {
-        return 0;
-    }
-
-    @Override
-    public int execCommands(String summaryForLogging, List<String> commands, Map<String, ?> env) {
-        return 0;
-    }
-
-    @Override
     public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env) {
         return 0;
     }
 
     @Override
-    public int execScript(String summaryForLogging, List<String> commands) {
-        return 0;
-    }
-
-    @Override
-    public int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands) {
-        return 0;
-    }
-
-    @Override
-    public int execScript(String summaryForLogging, List<String> commands, Map<String, ?> env) {
-        return 0;
-    }
-
-    @Override
     public int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env) {
         return 0;
     }
diff --git a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java
index 1198697..37898f3 100644
--- a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java
+++ b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java
@@ -205,42 +205,12 @@ public class WinRmMachineLocation extends AbstractMachineLocation implements Mac
     }
 
     @Override
-    public int execCommands(String summaryForLogging, List<String> commands) {
-        return executeCommand(commands).getStatusCode();
-    }
-
-    @Override
-    public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands) {
-        return executeCommand(props, commands).getStatusCode();
-    }
-
-    @Override
-    public int execCommands(String summaryForLogging, List<String> commands, Map<String, ?> env) {
-        return executeCommand(ImmutableMap.of(Winrm4jTool.ENVIRONMENT, env),commands).getStatusCode();
-    }
-
-    @Override
     public int execCommands(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env) {
         ImmutableMap<Object, Object> properties = ImmutableMap.builder().putAll(props).put(Winrm4jTool.ENVIRONMENT, env).build();
         return executeCommand(properties, commands).getStatusCode();
     }
 
     @Override
-    public int execScript(String summaryForLogging, List<String> commands) {
-        return executePsScript(commands).getStatusCode();
-    }
-
-    @Override
-    public int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands) {
-        return executePsScript(props, commands).getStatusCode();
-    }
-
-    @Override
-    public int execScript(String summaryForLogging, List<String> commands, Map<String, ?> env) {
-        return executePsScript(ImmutableMap.of(Winrm4jTool.ENVIRONMENT,env), commands).getStatusCode();
-    }
-
-    @Override
     public int execScript(Map<String, ?> props, String summaryForLogging, List<String> commands, Map<String, ?> env) {
         ImmutableMap<Object, Object> properties = ImmutableMap.builder().putAll(props).put(Winrm4jTool.ENVIRONMENT, env).build();
         return executePsScript(properties, commands).getStatusCode();
@@ -556,12 +526,12 @@ public class WinRmMachineLocation extends AbstractMachineLocation implements Mac
             sgsO.setLogPrefix("[curl @ "+getAddress()+":stdout] ").start();
             sgsE.setLogPrefix("[curl @ "+getAddress()+":stderr] ").start();
             Map<String, ?> winrmProps = MutableMap.<String, Object>builder().putAll(props).put("out", outO).put("err", outE).build();
-//            int result = execScript(winrmProps,"",ImmutableList.of(
-//                    "$WebClient = New-Object System.Net.WebClient",
-//                    "$WebClient.DownloadFile(" + url + "," + destPath + ")"
-//            ));
-
-            int result = 1;
+            ImmutableList<String> commands = ImmutableList.of(
+                    "echo $WebClient = New-Object System.Net.WebClient > C:\\temp.ps1",
+                    "echo $WebClient.DownloadFile(" + url + "," + destPath + ") >> C:\\temp.ps1",
+                    "powershell -c c:\\temp.ps1"
+            );
+            int result = execCommands(winrmProps,"", commands, ImmutableMap.of());
 
             if (result != 0) {
                 LOG.debug("installing {} to {} on {}, curl failed, attempting local fetch and copy", new Object[] { url, destPath, this });
diff --git a/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java b/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java
index 784e7d1..4295168 100644
--- a/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java
+++ b/software/winrm/src/main/java/org/apache/brooklyn/util/core/internal/winrm/winrm4j/Winrm4jTool.java
@@ -115,19 +115,12 @@ public class Winrm4jTool implements org.apache.brooklyn.util.core.internal.winrm
 
     @Override
     public org.apache.brooklyn.util.core.internal.winrm.WinRmToolResponse executeCommand(final List<String> commands) {
-        return exec(new Function<io.cloudsoft.winrm4j.winrm.WinRmTool, io.cloudsoft.winrm4j.winrm.WinRmToolResponse>() {
-            @Override public WinRmToolResponse apply(io.cloudsoft.winrm4j.winrm.WinRmTool tool) {
-                OutputStream outputStream = bag.get(ShellTool.PROP_OUT_STREAM);
-                OutputStream errorStream = bag.get(ShellTool.PROP_ERR_STREAM);
-                try(Writer out = outputStream != null ? new OutputStreamWriter(outputStream): new StringWriter();
-                Writer err = errorStream != null ? new OutputStreamWriter(errorStream): new StringWriter()) {
-                    return tool.executeCommand(commands, out, err);
-                } catch (IOException e) {
-                    // TODO Duncan
-                    e.printStackTrace();
-                    return null;
-                }
-            }
+        return exec(tool -> {
+            OutputStream outputStream = bag.get(ShellTool.PROP_OUT_STREAM);
+            OutputStream errorStream = bag.get(ShellTool.PROP_ERR_STREAM);
+            Writer out = outputStream != null ? new OutputStreamWriter(outputStream): new StringWriter();
+            Writer err = errorStream != null ? new OutputStreamWriter(errorStream): new StringWriter();
+            return tool.executeCommand(commands, out, err);
         });
     }
 
@@ -136,17 +129,15 @@ public class Winrm4jTool implements org.apache.brooklyn.util.core.internal.winrm
     public org.apache.brooklyn.util.core.internal.winrm.WinRmToolResponse executeScript(final List<String> commands) {
         return executeCommand(commands);
     }
-    
+
     @Override
     public org.apache.brooklyn.util.core.internal.winrm.WinRmToolResponse executePs(final List<String> commands) {
-        return exec(new Function<io.cloudsoft.winrm4j.winrm.WinRmTool, io.cloudsoft.winrm4j.winrm.WinRmToolResponse>() {
-            @Override public WinRmToolResponse apply(io.cloudsoft.winrm4j.winrm.WinRmTool tool) {
-                OutputStream outputStream = bag.get(ShellTool.PROP_OUT_STREAM);
-                OutputStream errorStream = bag.get(ShellTool.PROP_ERR_STREAM);
-                Writer out = outputStream != null ? new OutputStreamWriter(outputStream): new StringWriter();
-                Writer err = errorStream != null ? new OutputStreamWriter(errorStream): new StringWriter();
-                return tool.executePs(commands, out, err);
-            }
+        return exec(tool -> {
+            OutputStream outputStream = bag.get(ShellTool.PROP_OUT_STREAM);
+            OutputStream errorStream = bag.get(ShellTool.PROP_ERR_STREAM);
+            Writer out = outputStream != null ? new OutputStreamWriter(outputStream): new StringWriter();
+            Writer err = errorStream != null ? new OutputStreamWriter(errorStream): new StringWriter();
+            return tool.executePs(commands, out, err);
         });
     }
 
@@ -161,9 +152,9 @@ public class Winrm4jTool implements org.apache.brooklyn.util.core.internal.winrm
             int i=0;
             while ((bytesRead = source.read(inputData)) > 0) {
                 i++;
-                
+
                 LOG.debug("Copying chunk "+i+" to "+destination+" on "+host);
-                
+
                 byte[] chunk;
                 if (bytesRead == chunkSize) {
                     chunk = inputData;
@@ -176,7 +167,7 @@ public class Winrm4jTool implements org.apache.brooklyn.util.core.internal.winrm
                 expectedFileSize += bytesRead;
             }
             LOG.debug("Finished copying to "+destination+" on "+host);
-            
+
             return new org.apache.brooklyn.util.core.internal.winrm.WinRmToolResponse("", "", 0);
         } catch (java.io.IOException e) {
             throw propagate(e, "Failed copying to server at "+destination);
@@ -186,7 +177,7 @@ public class Winrm4jTool implements org.apache.brooklyn.util.core.internal.winrm
     private org.apache.brooklyn.util.core.internal.winrm.WinRmToolResponse exec(Function<io.cloudsoft.winrm4j.winrm.WinRmTool, io.cloudsoft.winrm4j.winrm.WinRmToolResponse> task) {
         Collection<Throwable> exceptions = Lists.newArrayList();
         Stopwatch totalStopwatch = Stopwatch.createStarted();
-        
+
         for (int i = 0; i < execTries; i++) {
             Stopwatch stopwatch = Stopwatch.createStarted();
             Duration connectTimestamp = null;
@@ -212,7 +203,7 @@ public class Winrm4jTool implements org.apache.brooklyn.util.core.internal.winrm
                 String timeMsg = "total time "+Duration.of(totalStopwatch).toStringRounded()
                         + ", this attempt failed after "+Duration.of(failTimestamp).toStringRounded()
                         + (connectTimestamp != null ? ", connected in "+Duration.of(connectTimestamp).toStringRounded() : "");
-                
+
                 if ((i + 1) == execTries) {
                     LOG.info("Propagating exception - WinRM failed on "+user+"@"+host+":"+port+" "
                             + (logCredentials ? "password=" + password : "")