This is an automated email from the ASF dual-hosted git repository. heneveld pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit 3b56db700b251150e02345bb3e8f24f9fc447b1e Author: Duncan Grant <[email protected]> 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 ---- pom.xml | 2 +- ...Factory.java => PlainWinRmExecTaskFactory.java} | 26 +-- .../location/winrm/WinRmMachineLocation.java | 43 +---- .../location/winrm/WinRmPutTaskFactory.java | 120 +++++++++++++ .../brooklyn/location/winrm/WinRmPutTaskStub.java | 68 ++++++++ .../location/winrm/WinRmPutTaskWrapper.java | 185 +++++++++++++++++++++ .../winrm/{WinRMTasks.java => WinRmTasks.java} | 13 +- .../core/internal/winrm/winrm4j/Winrm4jTool.java | 45 ++--- 11 files changed, 421 insertions(+), 129 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/pom.xml b/pom.xml index 1c56a1a..572103e 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-SNAPSHOT</winrm4j.version> <!-- FIXME NO CHECK IN --> + <winrm4j.version>0.10.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 similarity index 70% rename from software/winrm/src/main/java/org/apache/brooklyn/location/winrm/PlainWinRMExecTaskFactory.java rename to software/winrm/src/main/java/org/apache/brooklyn/location/winrm/PlainWinRmExecTaskFactory.java index 0fa344e..0fa3baf 100644 --- 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 @@ -25,47 +25,47 @@ import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; import java.util.List; -public class PlainWinRMExecTaskFactory<RET> extends AbstractSshExecTaskFactory<PlainSshExecTaskFactory<RET>,RET> { +public class PlainWinRmExecTaskFactory<RET> extends AbstractSshExecTaskFactory<PlainSshExecTaskFactory<RET>,RET> { /** constructor where machine will be added later */ - public PlainWinRMExecTaskFactory(String ...commands) { + public PlainWinRmExecTaskFactory(String ...commands) { super(commands); } /** convenience constructor to supply machine immediately */ - public PlainWinRMExecTaskFactory(WinRmMachineLocation machine, String ...commands) { + public PlainWinRmExecTaskFactory(WinRmMachineLocation machine, String ...commands) { this(commands); machine(machine); } /** Constructor where machine will be added later */ - public PlainWinRMExecTaskFactory(List<String> commands) { + 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) { + 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); + 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); + 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(); + public PlainWinRmExecTaskFactory<Boolean> returningIsExitCodeZero() { + return (PlainWinRmExecTaskFactory<Boolean>) super.returningIsExitCodeZero(); } @Override - public PlainWinRMExecTaskFactory<String> requiringZeroAndReturningStdout() { - return (PlainWinRMExecTaskFactory<String>) super.requiringZeroAndReturningStdout(); + public PlainWinRmExecTaskFactory<String> requiringZeroAndReturningStdout() { + return (PlainWinRmExecTaskFactory<String>) super.requiringZeroAndReturningStdout(); } } 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..efc0cb6 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,13 @@ 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( + "$tmp = New-TemporaryFile", + "echo $WebClient = New-Object System.Net.WebClient > $tmp.FullName", + "echo $WebClient.DownloadFile(" + url + "," + destPath + ") >> $tmp.FullName", + "powershell -c $tmp.FullName" + ); + 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/location/winrm/WinRmPutTaskFactory.java b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmPutTaskFactory.java new file mode 100644 index 0000000..23081bc --- /dev/null +++ b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmPutTaskFactory.java @@ -0,0 +1,120 @@ +/* + * 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.Suppliers; +import org.apache.brooklyn.api.mgmt.TaskFactory; +import org.apache.brooklyn.util.stream.KnownSizeInputStream; +import org.apache.brooklyn.util.stream.ReaderInputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; +import java.io.Reader; + +public class WinRmPutTaskFactory extends WinRmPutTaskStub implements TaskFactory<WinRmPutTaskWrapper> { + + private static final Logger log = LoggerFactory.getLogger(WinRmPutTaskFactory.class); + + private boolean dirty = false; + + /** constructor where machine will be added later */ + public WinRmPutTaskFactory(String remoteFile) { + remoteFile(remoteFile); + } + + /** convenience constructor to supply machine immediately */ + public WinRmPutTaskFactory(WinRmMachineLocation machine, String remoteFile) { + machine(machine); + remoteFile(remoteFile); + } + + protected WinRmPutTaskFactory self() { return this; } + + protected void markDirty() { + dirty = true; + } + + public WinRmPutTaskFactory machine(WinRmMachineLocation machine) { + markDirty(); + this.machine = machine; + return self(); + } + + public WinRmPutTaskFactory remoteFile(String remoteFile) { + this.remoteFile = remoteFile; + return self(); + } + + public WinRmPutTaskFactory summary(String summary) { + markDirty(); + this.summary = summary; + return self(); + } + + public WinRmPutTaskFactory contents(String contents) { + markDirty(); + this.contents = Suppliers.ofInstance(KnownSizeInputStream.of(contents)); + return self(); + } + + public WinRmPutTaskFactory contents(byte[] contents) { + markDirty(); + this.contents = Suppliers.ofInstance(KnownSizeInputStream.of(contents)); + return self(); + } + + public WinRmPutTaskFactory contents(InputStream stream) { + markDirty(); + this.contents = Suppliers.ofInstance(stream); + return self(); + } + + public WinRmPutTaskFactory contents(Reader reader) { + markDirty(); + this.contents = Suppliers.ofInstance(new ReaderInputStream(reader)); + return self(); + } + + public WinRmPutTaskFactory allowFailure() { + markDirty(); + allowFailure = true; + return self(); + } + + public WinRmPutTaskFactory createDirectory() { + markDirty(); + createDirectory = true; + return self(); + } + + @Override + public WinRmPutTaskWrapper newTask() { + dirty = false; + return new WinRmPutTaskWrapper(this); + } + + @Override + protected void finalize() throws Throwable { + // help let people know of API usage error + if (dirty) + log.warn("Task "+this+" was modified but modification was never used"); + super.finalize(); + } +} diff --git a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmPutTaskStub.java b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmPutTaskStub.java new file mode 100644 index 0000000..28a27bd --- /dev/null +++ b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmPutTaskStub.java @@ -0,0 +1,68 @@ +/* + * 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.Supplier; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.core.task.ssh.SshPutTaskStub; + +import java.io.InputStream; + +public class WinRmPutTaskStub { + protected String remoteFile; + protected WinRmMachineLocation machine; + protected Supplier<? extends InputStream> contents; + protected String summary; + protected String permissions; + protected boolean allowFailure = false; + protected boolean createDirectory = false; + protected final ConfigBag config = ConfigBag.newInstance(); + + protected WinRmPutTaskStub() { + } + + protected WinRmPutTaskStub(WinRmPutTaskStub constructor) { + this.remoteFile = constructor.remoteFile; + this.machine = constructor.machine; + this.contents = constructor.contents; + this.summary = constructor.summary; + this.allowFailure = constructor.allowFailure; + this.createDirectory = constructor.createDirectory; + this.permissions = constructor.permissions; + this.config.copy(constructor.config); + } + + public String getRemoteFile() { + return remoteFile; + } + + public String getSummary() { + if (summary!=null) return summary; + return "scp put: "+remoteFile; + } + + public WinRmMachineLocation getMachine() { + return machine; + } + + protected ConfigBag getConfig() { + return config; + } +} diff --git a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmPutTaskWrapper.java b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmPutTaskWrapper.java new file mode 100644 index 0000000..1315010 --- /dev/null +++ b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmPutTaskWrapper.java @@ -0,0 +1,185 @@ +/* + * 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.Preconditions; +import com.google.common.collect.ImmutableMap; +import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.api.mgmt.TaskWrapper; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.core.internal.ssh.SshTool; +import org.apache.brooklyn.util.core.task.TaskBuilder; +import org.apache.brooklyn.util.core.task.Tasks; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.concurrent.Callable; + +public class WinRmPutTaskWrapper extends WinRmPutTaskStub implements TaskWrapper<Void> { + private static final Logger log = LoggerFactory.getLogger(WinRmPutTaskWrapper.class); + + private final Task<Void> task; + + protected Integer exitCodeOfCopy = null; + protected Exception exception = null; + protected boolean successful = false; + + // package private as only AbstractWinRmTaskFactory should invoke + WinRmPutTaskWrapper(WinRmPutTaskFactory constructor) { + super(constructor); + TaskBuilder<Void> tb = TaskBuilder.<Void>builder().dynamic(false).displayName(getSummary()); + task = tb.body(new WinRmPutJob()).build(); + } + + @Override + public Task<Void> asTask() { + return getTask(); + } + + @Override + public Task<Void> getTask() { + return task; + } + + // TODO: + // verify + // copyAsRoot + // owner + // lastModificationDate - see {@link #PROP_LAST_MODIFICATION_DATE}; not supported by all SshTool implementations + // lastAccessDate - see {@link #PROP_LAST_ACCESS_DATE}; not supported by all SshTool implementations + + private class WinRmPutJob implements Callable<Void> { + @Override + public Void call() throws Exception { + try { + Preconditions.checkNotNull(getMachine(), "machine"); + + String remoteFile = getRemoteFile(); + + if (createDirectory) { + String remoteDir = remoteFile; + int exitCodeOfCreate = -1; + try { + int li = remoteDir.lastIndexOf("/"); + if (li>=0) { + remoteDir = remoteDir.substring(0, li+1); + exitCodeOfCreate = getMachine().execCommands(ImmutableMap.of(), "creating directory for "+getSummary(), + Arrays.asList("md "+remoteDir), ImmutableMap.of()); + } else { + // nothing to create + exitCodeOfCreate = 0; + } + } catch (Exception e) { + if (log.isDebugEnabled()) + log.debug("WinRM put "+getRemoteFile()+" (create dir, in task "+getSummary()+") to "+getMachine()+" threw exception: "+e); + exception = e; + } + if (exception!=null || !((Integer)0).equals(exitCodeOfCreate)) { + if (!allowFailure) { + if (exception != null) { + throw new IllegalStateException(getSummary()+" (creating dir "+remoteDir+" for WinRM put task) ended with exception, in "+ Tasks.current()+": "+exception, exception); + } + if (exitCodeOfCreate!=0) { + exception = new IllegalStateException(getSummary()+" (creating dir "+remoteDir+" WinRM put task) ended with exit code "+exitCodeOfCreate+", in "+Tasks.current()); + throw exception; + } + } + // not successful, but allowed + return null; + } + } + + ConfigBag config = ConfigBag.newInstanceCopying(getConfig()); + if (permissions!=null) config.put(SshTool.PROP_PERMISSIONS, permissions); + + exitCodeOfCopy = getMachine().copyTo(config.getAllConfig(), contents.get(), remoteFile); + + if (log.isDebugEnabled()) + log.debug("WinRM put "+getRemoteFile()+" (task "+getSummary()+") to "+getMachine()+" completed with exit code "+exitCodeOfCopy); + } catch (Exception e) { + if (log.isDebugEnabled()) + log.debug("WinRM put "+getRemoteFile()+" (task "+getSummary()+") to "+getMachine()+" threw exception: "+e); + exception = e; + } + + if (exception!=null || !((Integer)0).equals(exitCodeOfCopy)) { + if (!allowFailure) { + if (exception != null) { + throw new IllegalStateException(getSummary()+" (WinRM put task) ended with exception, in "+Tasks.current()+": "+exception, exception); + } + if (exitCodeOfCopy!=0) { + exception = new IllegalStateException(getSummary()+" (WinRM put task) ended with exit code "+exitCodeOfCopy+", in "+Tasks.current()); + throw exception; + } + } + // not successful, but allowed + return null; + } + + // TODO verify + + successful = (exception==null && ((Integer)0).equals(exitCodeOfCopy)); + return null; + } + } + + @Override + public String toString() { + return super.toString()+"["+task+"]"; + } + + /** blocks, throwing if there was an exception */ + public Void get() { + return getTask().getUnchecked(); + } + + /** returns the exit code from the copy, 0 on success; + * null if it has not completed or threw exception + * (not sure if this is ever a non-zero integer or if it is meaningful) + * <p> + * most callers will want the simpler {@link #isSuccessful()} */ + public Integer getExitCode() { + return exitCodeOfCopy; + } + + /** returns any exception encountered in the operation */ + public Exception getException() { + return exception; + } + + /** blocks until the task completes; does not throw + * @return*/ + public WinRmPutTaskWrapper block() { + getTask().blockUntilEnded(); + return this; + } + + /** true iff the ssh job has completed (with or without failure) */ + public boolean isDone() { + return getTask().isDone(); + } + + /** true iff the scp has completed successfully; guaranteed to be set before {@link #isDone()} or {@link #block()} are satisfied */ + public boolean isSuccessful() { + return successful; + } + + +} 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 similarity index 81% rename from software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRMTasks.java rename to software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinRmTasks.java index fb89ad5..7ae2663 100644 --- 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 @@ -20,8 +20,6 @@ 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; @@ -29,9 +27,9 @@ import org.apache.brooklyn.util.net.Urls; import java.util.Map; -public class WinRMTasks { +public class WinRmTasks { public static ProcessTaskFactory<Integer> newWinrmExecTaskFactory(org.apache.brooklyn.location.winrm.WinRmMachineLocation winRmMachineLocation, String ...commands) { - return new PlainWinRMExecTaskFactory<>(winRmMachineLocation, 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) { @@ -49,4 +47,11 @@ public class WinRMTasks { } }; } + + public static WinRmPutTaskFactory newWinrmPutTaskFactory(WinRmMachineLocation winRmMachineLocation, String remoteFile) { + return newWinRmPutTaskFactory(winRmMachineLocation, true, remoteFile); + } + public static WinRmPutTaskFactory newWinRmPutTaskFactory(WinRmMachineLocation machine, final boolean useMachineConfig, String remoteFile) { + return new WinRmPutTaskFactory(machine, remoteFile); + } } 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 : "")
