Adds support for getting return from WinRmMachineLocation execute commands
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/902f97e4 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/902f97e4 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/902f97e4 Branch: refs/heads/master Commit: 902f97e48c02c4c82f6e27fdcd0fc209dd2ead3b Parents: 96f2f1c Author: Martin Harris <[email protected]> Authored: Tue May 12 15:56:09 2015 +0100 Committer: Richard Downer <[email protected]> Committed: Thu May 28 17:27:35 2015 +0100 ---------------------------------------------------------------------- .../java/brooklyn/entity/effector/EffectorTasks.java | 10 ++++++++++ .../main/java/brooklyn/location/basic/Machines.java | 6 +++++- .../brooklyn/location/basic/WinRmMachineLocation.java | 14 +++++++------- .../main/java/brooklyn/util/flags/TypeCoercions.java | 8 ++++++++ .../brooklyn/util/internal/TypeCoercionsTest.java | 7 +++++++ .../brooklyn/location/jclouds/JcloudsLocation.java | 5 ++--- .../basic/AbstractSoftwareProcessWinRmDriver.java | 13 +++++++------ 7 files changed, 46 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/902f97e4/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java b/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java index 98e3348..83d27ea 100644 --- a/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java +++ b/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java @@ -33,6 +33,7 @@ import brooklyn.entity.basic.BrooklynTaskTags; import brooklyn.entity.basic.ConfigKeys; import brooklyn.location.basic.Machines; import brooklyn.location.basic.SshMachineLocation; +import brooklyn.location.basic.WinRmMachineLocation; import brooklyn.management.Task; import brooklyn.management.TaskAdaptable; import brooklyn.management.internal.EffectorUtils; @@ -217,4 +218,13 @@ public class EffectorTasks { } } + /** Finds a unique {@link WinRmMachineLocation} attached to the supplied entity + * @throws IllegalStateException if there is not a unique such {@link WinRmMachineLocation} */ + public static WinRmMachineLocation getWinRmMachine(Entity entity) { + try { + return Machines.findUniqueWinRmMachineLocation(entity.getLocations()).get(); + } catch (Exception e) { + throw new IllegalStateException("Entity "+entity+" (in "+Tasks.current()+") requires a single WinRmMachineLocation, but has "+entity.getLocations(), e); + } + } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/902f97e4/core/src/main/java/brooklyn/location/basic/Machines.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/location/basic/Machines.java b/core/src/main/java/brooklyn/location/basic/Machines.java index 1f36a16..103870f 100644 --- a/core/src/main/java/brooklyn/location/basic/Machines.java +++ b/core/src/main/java/brooklyn/location/basic/Machines.java @@ -95,6 +95,10 @@ public class Machines { return findUniqueElement(locations, SshMachineLocation.class); } + public static Maybe<WinRmMachineLocation> findUniqueWinRmMachineLocation(Iterable<? extends Location> locations) { + return findUniqueElement(locations, WinRmMachineLocation.class); + } + public static Maybe<String> findSubnetHostname(Iterable<? extends Location> ll) { Maybe<MachineLocation> l = findUniqueMachineLocation(ll); if (!l.isPresent()) { @@ -169,5 +173,5 @@ public class Machines { } return false; } - + } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/902f97e4/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java b/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java index 6ca6869..d535d34 100644 --- a/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java +++ b/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java @@ -101,17 +101,17 @@ public class WinRmMachineLocation extends AbstractLocation implements MachineLoc return null; } - public int executeScript(String script) { + public WinRmToolResponse executeScript(String script) { return executeScript(ImmutableList.of(script)); } - public int executeScript(List<String> script) { + public WinRmToolResponse executeScript(List<String> script) { Collection<Throwable> exceptions = Lists.newArrayList(); for (int i = 0; i < 10; i++) { try { WinRmTool winRmTool = WinRmTool.connect(getHostname(), getUsername(), getPassword()); WinRmToolResponse response = winRmTool.executeScript(script); - return response.getStatusCode(); + return response; } catch (Exception e) { LOG.warn("ignoring winrm exception and retrying:", e); exceptions.add(e); @@ -120,17 +120,17 @@ public class WinRmMachineLocation extends AbstractLocation implements MachineLoc throw Exceptions.propagate("failed to execute powershell script", exceptions); } - public int executePsScript(String psScript) { + public WinRmToolResponse executePsScript(String psScript) { return executePsScript(ImmutableList.of(psScript)); } - public int executePsScript(List<String> psScript) { + public WinRmToolResponse executePsScript(List<String> psScript) { Collection<Throwable> exceptions = Lists.newArrayList(); for (int i = 0; i < 10; i++) { try { WinRmTool winRmTool = WinRmTool.connect(getHostname(), getUsername(), getPassword()); WinRmToolResponse response = winRmTool.executePs(psScript); - return response.getStatusCode(); + return response; } catch (Exception e) { LOG.warn("ignoring winrm exception and retrying after 5 seconds:", e); Time.sleep(Duration.FIVE_SECONDS); @@ -187,7 +187,7 @@ public class WinRmMachineLocation extends AbstractLocation implements MachineLoc String unencodePowershell = "$RDP = Get-WmiObject -Class Win32_TerminalServiceSetting -ComputerName $env:computername -Namespace root\\CIMV2\\TerminalServices -Authentication PacketPrivacy\r\n" + "$RDP.SetAllowTSConnections(1,1)\r\n" + - "Set-ExecutionPolicy Unrestricted\r\n" + + "Set-ExecutionPolicy Unrestricted -Force\r\n" + "Set-Item WSMan:\\localhost\\Shell\\MaxConcurrentUsers 100\r\n" + "Set-Item WSMan:\\localhost\\Shell\\MaxMemoryPerShellMB 0\r\n" + "Set-Item WSMan:\\localhost\\Shell\\MaxProcessesPerShell 0\r\n" + http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/902f97e4/core/src/main/java/brooklyn/util/flags/TypeCoercions.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java b/core/src/main/java/brooklyn/util/flags/TypeCoercions.java index 6c6ecac..74ada77 100644 --- a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java +++ b/core/src/main/java/brooklyn/util/flags/TypeCoercions.java @@ -31,6 +31,7 @@ import java.math.BigInteger; import java.net.InetAddress; import java.net.URI; import java.net.URL; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -709,6 +710,13 @@ public class TypeCoercions { return QuorumChecks.of(input); } }); + registerAdapter(ArrayList.class, String[].class, new Function<ArrayList, String[]>() { + @Nullable + @Override + public String[] apply(@Nullable ArrayList arrayList) { + return (String[]) arrayList.toArray(new String[]{}); + } + }); registerAdapter(String.class, Map.class, new Function<String,Map>() { @Override public Map apply(final String input) { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/902f97e4/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java b/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java index b4d0470..3133b22 100644 --- a/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java +++ b/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java @@ -22,6 +22,7 @@ import static org.testng.Assert.assertEquals; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -42,6 +43,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; import com.google.common.reflect.TypeToken; public class TypeCoercionsTest { @@ -307,6 +309,11 @@ public class TypeCoercionsTest { assertEquals(TypeCoercions.coerce("1.0", Number.class), (Number) Double.valueOf(1.0)); } + @Test + public void testArrayListToArray() { + assertEquals(TypeCoercions.coerce(Lists.newArrayList("Foo", "Bar", "Baz"), String[].class), new String[] {"Foo", "Bar", "Baz"}); + } + @Test(expectedExceptions = ClassCoercionException.class) public void testInvalidCoercionThrowsClassCoercionException() { TypeCoercions.coerce(new Object(), TypeToken.of(Integer.class)); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/902f97e4/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java index 3aeaf13..7a2a0da 100644 --- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java @@ -1255,8 +1255,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im LOG.warn("Ignoring request to set template option {} because this is not supported by {}", new Object[] { option.getKey(), clazz.getCanonicalName() }); } } - } - }) + }}) .build(); /** hook whereby template customizations can be made for various clouds */ @@ -2018,7 +2017,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im try { // FIXME: Needs to release port forwarding for WinRmMachineLocations - if (machine.getMachineDetails().getOsDetails() != null && !machine.getMachineDetails().getOsDetails().isWindows()) { + if (machine.getMachineDetails() != null && machine.getMachineDetails().getOsDetails() != null && !machine.getMachineDetails().getOsDetails().isWindows()) { releasePortForwarding((SshMachineLocation)machine); } } catch (Exception e) { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/902f97e4/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessWinRmDriver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessWinRmDriver.java b/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessWinRmDriver.java index d865c4d..af6a80c 100644 --- a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessWinRmDriver.java +++ b/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessWinRmDriver.java @@ -27,6 +27,7 @@ import brooklyn.config.ConfigKey; import brooklyn.event.AttributeSensor; import brooklyn.event.basic.Sensors; import brooklyn.location.basic.WinRmMachineLocation; +import io.cloudsoft.winrm4j.winrm.WinRmToolResponse; import com.google.api.client.util.Strings; import com.google.common.collect.ImmutableList; @@ -107,12 +108,12 @@ public abstract class AbstractSoftwareProcessWinRmDriver extends AbstractSoftwar getLocation().executePsScript("New-Item -path \"" + directoryName + "\" -type directory -ErrorAction SilentlyContinue"); } - protected boolean executeCommand(ConfigKey<String> regularCommandKey, ConfigKey<String> powershellCommandKey, boolean allowNoOp) { + protected WinRmToolResponse executeCommand(ConfigKey<String> regularCommandKey, ConfigKey<String> powershellCommandKey, boolean allowNoOp) { String regularCommand = getEntity().getConfig(regularCommandKey); String powershellCommand = getEntity().getConfig(powershellCommandKey); if (Strings.isNullOrEmpty(regularCommand) && Strings.isNullOrEmpty(powershellCommand)) { if (allowNoOp) { - return true; + return new WinRmToolResponse("", "", 0); } else { throw new IllegalStateException(String.format("Exactly one of %s or %s must be set", regularCommandKey.getName(), powershellCommandKey.getName())); } @@ -121,18 +122,18 @@ public abstract class AbstractSoftwareProcessWinRmDriver extends AbstractSoftwar } if (Strings.isNullOrEmpty(regularCommand)) { - return getLocation().executePsScript(ImmutableList.of(powershellCommand)) == 0; + return getLocation().executePsScript(ImmutableList.of(powershellCommand)); } else { - return getLocation().executeScript(ImmutableList.of(regularCommand)) == 0; + return getLocation().executeScript(ImmutableList.of(regularCommand)); } } public int execute(List<String> script) { - return getLocation().executeScript(script); + return getLocation().executeScript(script).getStatusCode(); } public int executePowerShell(List<String> psScript) { - return getLocation().executePsScript(psScript); + return getLocation().executePsScript(psScript).getStatusCode(); } public int copyTo(File source, File destination) {
