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 <[email protected]> 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; + } } }); }
