[BROOKLYN-182] Move winrm-dependent code from brooklyn-core to brooklyn-software-winrm
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/8fa4df7d Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/8fa4df7d Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/8fa4df7d Branch: refs/heads/master Commit: 8fa4df7ddd525883553c5c57828426da31961020 Parents: 49eabd1 Author: Ciprian Ciubotariu <[email protected]> Authored: Wed Oct 14 17:15:56 2015 +0300 Committer: Ciprian Ciubotariu <[email protected]> Committed: Wed Oct 14 23:36:22 2015 +0300 ---------------------------------------------------------------------- core/pom.xml | 5 - .../location/access/BrooklynAccessUtils.java | 3 +- .../WindowsPerformanceCounterSensors.java | 73 ---- .../windows/WindowsPerformanceCounterFeed.java | 412 ------------------ .../winrm/AdvertiseWinrmLoginPolicy.java | 80 ---- .../location/winrm/WinRmMachineLocation.java | 362 ---------------- .../core/plan/XmlPlanToSpecTransformerTest.java | 2 +- .../WindowsPerformanceCounterFeedLiveTest.java | 104 ----- .../WindowsPerformanceCounterFeedTest.java | 132 ------ .../winrm/AdvertiseWinrmLoginPolicyTest.java | 51 --- .../winrm/WinRmMachineLocationTest.java | 44 -- pom.xml | 1 + software/winrm/pom.xml | 45 ++ .../WindowsPerformanceCounterSensors.java | 73 ++++ .../windows/WindowsPerformanceCounterFeed.java | 414 +++++++++++++++++++ .../winrm/AdvertiseWinrmLoginPolicy.java | 80 ++++ .../location/winrm/WinRmMachineLocation.java | 362 ++++++++++++++++ .../WindowsPerformanceCounterFeedLiveTest.java | 103 +++++ .../WindowsPerformanceCounterFeedTest.java | 130 ++++++ .../winrm/AdvertiseWinrmLoginPolicyTest.java | 49 +++ .../winrm/WinRmMachineLocationTest.java | 43 ++ 21 files changed, 1302 insertions(+), 1266 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/pom.xml ---------------------------------------------------------------------- diff --git a/core/pom.xml b/core/pom.xml index 7239baf..66ac533 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -54,11 +54,6 @@ <version>${project.version}</version> </dependency> <dependency> - <groupId>io.cloudsoft.windows</groupId> - <artifactId>winrm4j</artifactId> - <version>${winrm4j.version}</version> - </dependency> - <dependency> <groupId>net.schmizz</groupId> <artifactId>sshj</artifactId> </dependency> http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/main/java/org/apache/brooklyn/core/location/access/BrooklynAccessUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/location/access/BrooklynAccessUtils.java b/core/src/main/java/org/apache/brooklyn/core/location/access/BrooklynAccessUtils.java index 1ac354f..b36ddf6 100644 --- a/core/src/main/java/org/apache/brooklyn/core/location/access/BrooklynAccessUtils.java +++ b/core/src/main/java/org/apache/brooklyn/core/location/access/BrooklynAccessUtils.java @@ -39,8 +39,7 @@ import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.net.Cidr; import org.apache.brooklyn.util.text.Strings; -import org.python.google.common.base.Predicates; -import org.python.google.common.collect.Iterables; +import com.google.common.collect.Iterables; import com.google.common.base.Supplier; import com.google.common.net.HostAndPort; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/main/java/org/apache/brooklyn/core/sensor/windows/WindowsPerformanceCounterSensors.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/windows/WindowsPerformanceCounterSensors.java b/core/src/main/java/org/apache/brooklyn/core/sensor/windows/WindowsPerformanceCounterSensors.java deleted file mode 100644 index f5c2271..0000000 --- a/core/src/main/java/org/apache/brooklyn/core/sensor/windows/WindowsPerformanceCounterSensors.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.core.sensor.windows; - -import java.util.Map; -import java.util.Set; - -import org.apache.brooklyn.api.entity.EntityInitializer; -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.core.sensor.Sensors; -import org.apache.brooklyn.feed.windows.WindowsPerformanceCounterFeed; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.text.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.reflect.TypeToken; - -public class WindowsPerformanceCounterSensors implements EntityInitializer { - - private static final Logger LOG = LoggerFactory.getLogger(WindowsPerformanceCounterSensors.class); - - public final static ConfigKey<Set<Map<String, String>>> PERFORMANCE_COUNTERS = ConfigKeys.newConfigKey(new TypeToken<Set<Map<String, String>>>(){}, "performance.counters"); - - protected final Set<Map<String, String>> sensors; - - public WindowsPerformanceCounterSensors(ConfigBag params) { - sensors = params.get(PERFORMANCE_COUNTERS); - } - - public WindowsPerformanceCounterSensors(Map<String, String> params) { - this(ConfigBag.newInstance(params)); - } - - @Override - public void apply(EntityLocal entity) { - WindowsPerformanceCounterFeed.Builder builder = WindowsPerformanceCounterFeed.builder() - .entity(entity); - for (Map<String, String> sensorConfig : sensors) { - String name = sensorConfig.get("name"); - String sensorType = sensorConfig.get("sensorType"); - Class<?> clazz; - try { - clazz = Strings.isNonEmpty(sensorType) - ? ((EntityInternal)entity).getManagementContext().getCatalog().getRootClassLoader().loadClass(sensorType) - : String.class; - } catch (ClassNotFoundException e) { - throw new IllegalStateException("Could not load type "+sensorType+" for sensor "+name, e); - } - builder.addSensor(sensorConfig.get("counter"), Sensors.newSensor(clazz, name, sensorConfig.get("description"))); - } - builder.build(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/main/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeed.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeed.java b/core/src/main/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeed.java deleted file mode 100644 index 07cb8ea..0000000 --- a/core/src/main/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeed.java +++ /dev/null @@ -1,412 +0,0 @@ -/* - * 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.feed.windows; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import io.cloudsoft.winrm4j.winrm.WinRmToolResponse; - -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.annotation.Nullable; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.api.mgmt.ExecutionContext; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.effector.EffectorTasks; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.core.feed.AbstractFeed; -import org.apache.brooklyn.core.feed.PollHandler; -import org.apache.brooklyn.core.feed.Poller; -import org.apache.brooklyn.core.sensor.Sensors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.brooklyn.location.winrm.WinRmMachineLocation; -import org.apache.brooklyn.util.core.flags.TypeCoercions; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.time.Duration; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; -import com.google.common.base.Joiner; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.reflect.TypeToken; - -/** - * A sensor feed that retrieves performance counters from a Windows host and posts the values to sensors. - * - * <p>To use this feed, you must provide the entity, and a collection of mappings between Windows performance counter - * names and Brooklyn attribute sensors.</p> - * - * <p>This feed uses SSH to invoke the windows utility <tt>typeperf</tt> to query for a specific set of performance - * counters, by name. The values are extracted from the response, and published to the entity's sensors.</p> - * - * <p>Example:</p> - * - * {@code - * @Override - * protected void connectSensors() { - * WindowsPerformanceCounterFeed feed = WindowsPerformanceCounterFeed.builder() - * .entity(entity) - * .addSensor("\\Processor(_total)\\% Idle Time", CPU_IDLE_TIME) - * .addSensor("\\Memory\\Available MBytes", AVAILABLE_MEMORY) - * .build(); - * } - * } - * - * @since 0.6.0 - * @author richardcloudsoft - */ -public class WindowsPerformanceCounterFeed extends AbstractFeed { - - private static final Logger log = LoggerFactory.getLogger(WindowsPerformanceCounterFeed.class); - - // This pattern matches CSV line(s) with the date in the first field, and at least one further field. - protected static final Pattern lineWithPerfData = Pattern.compile("^\"[\\d:/\\-. ]+\",\".*\"$", Pattern.MULTILINE); - private static final Joiner JOINER_ON_SPACE = Joiner.on(' '); - private static final Joiner JOINER_ON_COMMA = Joiner.on(','); - private static final int OUTPUT_COLUMN_WIDTH = 100; - - @SuppressWarnings("serial") - public static final ConfigKey<Collection<WindowsPerformanceCounterPollConfig<?>>> POLLS = ConfigKeys.newConfigKey( - new TypeToken<Collection<WindowsPerformanceCounterPollConfig<?>>>() {}, - "polls"); - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private EntityLocal entity; - private Set<WindowsPerformanceCounterPollConfig<?>> polls = Sets.newLinkedHashSet(); - private Duration period = Duration.of(30, TimeUnit.SECONDS); - private String uniqueTag; - private volatile boolean built; - - public Builder entity(EntityLocal val) { - this.entity = checkNotNull(val, "entity"); - return this; - } - public Builder addSensor(WindowsPerformanceCounterPollConfig<?> config) { - polls.add(config); - return this; - } - public Builder addSensor(String performanceCounterName, AttributeSensor<?> sensor) { - return addSensor(new WindowsPerformanceCounterPollConfig(sensor).performanceCounterName(checkNotNull(performanceCounterName, "performanceCounterName"))); - } - public Builder addSensors(Map<String, AttributeSensor> sensors) { - for (Map.Entry<String, AttributeSensor> entry : sensors.entrySet()) { - addSensor(entry.getKey(), entry.getValue()); - } - return this; - } - public Builder period(Duration period) { - this.period = checkNotNull(period, "period"); - return this; - } - public Builder period(long millis) { - return period(millis, TimeUnit.MILLISECONDS); - } - public Builder period(long val, TimeUnit units) { - return period(Duration.of(val, units)); - } - public Builder uniqueTag(String uniqueTag) { - this.uniqueTag = uniqueTag; - return this; - } - public WindowsPerformanceCounterFeed build() { - built = true; - WindowsPerformanceCounterFeed result = new WindowsPerformanceCounterFeed(this); - result.setEntity(checkNotNull(entity, "entity")); - result.start(); - return result; - } - @Override - protected void finalize() { - if (!built) log.warn("WindowsPerformanceCounterFeed.Builder created, but build() never called"); - } - } - - /** - * For rebind; do not call directly; use builder - */ - public WindowsPerformanceCounterFeed() { - } - - protected WindowsPerformanceCounterFeed(Builder builder) { - List<WindowsPerformanceCounterPollConfig<?>> polls = Lists.newArrayList(); - for (WindowsPerformanceCounterPollConfig<?> config : builder.polls) { - if (!config.isEnabled()) continue; - @SuppressWarnings({ "unchecked", "rawtypes" }) - WindowsPerformanceCounterPollConfig<?> configCopy = new WindowsPerformanceCounterPollConfig(config); - if (configCopy.getPeriod() < 0) configCopy.period(builder.period); - polls.add(configCopy); - } - config().set(POLLS, polls); - initUniqueTag(builder.uniqueTag, polls); - } - - @Override - protected void preStart() { - Collection<WindowsPerformanceCounterPollConfig<?>> polls = getConfig(POLLS); - - long minPeriod = Integer.MAX_VALUE; - List<String> performanceCounterNames = Lists.newArrayList(); - for (WindowsPerformanceCounterPollConfig<?> config : polls) { - minPeriod = Math.min(minPeriod, config.getPeriod()); - performanceCounterNames.add(config.getPerformanceCounterName()); - } - - Iterable<String> allParams = ImmutableList.<String>builder() - .add("(Get-Counter") - .add("-Counter") - .add(JOINER_ON_COMMA.join(Iterables.transform(performanceCounterNames, QuoteStringFunction.INSTANCE))) - .add("-SampleInterval") - .add("2") // TODO: extract SampleInterval as a config key - .add(").CounterSamples") - .add("|") - .add("Format-Table") - .add(String.format("@{Expression={$_.Path};width=%d},@{Expression={$_.CookedValue};width=%<d}", OUTPUT_COLUMN_WIDTH)) - .add("-HideTableHeaders") - .add("|") - .add("Out-String") - .add("-Width") - .add(String.valueOf(OUTPUT_COLUMN_WIDTH * 2)) - .build(); - String command = JOINER_ON_SPACE.join(allParams); - log.debug("Windows performance counter poll command for {} will be: {}", entity, command); - - GetPerformanceCountersJob<WinRmToolResponse> job = new GetPerformanceCountersJob(getEntity(), command); - getPoller().scheduleAtFixedRate( - new CallInEntityExecutionContext(entity, job), - new SendPerfCountersToSensors(getEntity(), polls), - minPeriod); - } - - private static class GetPerformanceCountersJob<T> implements Callable<T> { - - private final Entity entity; - private final String command; - - GetPerformanceCountersJob(Entity entity, String command) { - this.entity = entity; - this.command = command; - } - - @Override - public T call() throws Exception { - WinRmMachineLocation machine = EffectorTasks.getWinRmMachine(entity); - WinRmToolResponse response = machine.executePsScript(command); - return (T)response; - } - } - - @SuppressWarnings("unchecked") - protected Poller<WinRmToolResponse> getPoller() { - return (Poller<WinRmToolResponse>) super.getPoller(); - } - - /** - * A {@link java.util.concurrent.Callable} that wraps another {@link java.util.concurrent.Callable}, where the - * inner {@link java.util.concurrent.Callable} is executed in the context of a - * specific entity. - * - * @param <T> The type of the {@link java.util.concurrent.Callable}. - */ - private static class CallInEntityExecutionContext<T> implements Callable<T> { - private final Callable<T> job; - private EntityLocal entity; - - private CallInEntityExecutionContext(EntityLocal entity, Callable<T> job) { - this.job = job; - this.entity = entity; - } - - @Override - public T call() throws Exception { - ExecutionContext executionContext = ((EntityInternal) entity).getManagementSupport().getExecutionContext(); - return executionContext.submit(Maps.newHashMap(), job).get(); - } - } - - @VisibleForTesting - static class SendPerfCountersToSensors implements PollHandler<WinRmToolResponse> { - private final EntityLocal entity; - private final List<WindowsPerformanceCounterPollConfig<?>> polls; - private final Set<AttributeSensor<?>> failedAttributes = Sets.newLinkedHashSet(); - private static final Pattern MACHINE_NAME_LOOKBACK_PATTERN = Pattern.compile(String.format("(?<=\\\\\\\\.{0,%d})\\\\.*", OUTPUT_COLUMN_WIDTH)); - - public SendPerfCountersToSensors(EntityLocal entity, Collection<WindowsPerformanceCounterPollConfig<?>> polls) { - this.entity = entity; - this.polls = ImmutableList.copyOf(polls); - } - - @Override - public boolean checkSuccess(WinRmToolResponse val) { - // TODO not just using statusCode; also looking at absence of stderr. - // Status code is (empirically) unreliable: it returns 0 sometimes even when failed - // (but never returns non-zero on success). - if (val.getStatusCode() != 0) return false; - String stderr = val.getStdErr(); - if (stderr == null || stderr.length() != 0) return false; - String out = val.getStdOut(); - if (out == null || out.length() == 0) return false; - return true; - } - - @Override - public void onSuccess(WinRmToolResponse val) { - for (String pollResponse : val.getStdOut().split("\r\n")) { - if (Strings.isNullOrEmpty(pollResponse)) { - continue; - } - String path = pollResponse.substring(0, OUTPUT_COLUMN_WIDTH - 1); - // The performance counter output prepends the sensor name with "\\<machinename>" so we need to remove it - Matcher machineNameLookbackMatcher = MACHINE_NAME_LOOKBACK_PATTERN.matcher(path); - if (!machineNameLookbackMatcher.find()) { - continue; - } - String name = machineNameLookbackMatcher.group(0).trim(); - String rawValue = pollResponse.substring(OUTPUT_COLUMN_WIDTH).replaceAll("^\\s+", ""); - WindowsPerformanceCounterPollConfig<?> config = getPollConfig(name); - Class<?> clazz = config.getSensor().getType(); - AttributeSensor<Object> attribute = (AttributeSensor<Object>) Sensors.newSensor(clazz, config.getSensor().getName(), config.getDescription()); - try { - Object value = TypeCoercions.coerce(rawValue, TypeToken.of(clazz)); - entity.sensors().set(attribute, value); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - if (failedAttributes.add(attribute)) { - log.warn("Failed to coerce value '{}' to {} for {} -> {}", new Object[] {rawValue, clazz, entity, attribute}); - } else { - if (log.isTraceEnabled()) log.trace("Failed (repeatedly) to coerce value '{}' to {} for {} -> {}", new Object[] {rawValue, clazz, entity, attribute}); - } - } - } - } - - @Override - public void onFailure(WinRmToolResponse val) { - log.error("Windows Performance Counter query did not respond as expected. exitcode={} stdout={} stderr={}", - new Object[]{val.getStatusCode(), val.getStdOut(), val.getStdErr()}); - for (WindowsPerformanceCounterPollConfig<?> config : polls) { - Class<?> clazz = config.getSensor().getType(); - AttributeSensor<?> attribute = Sensors.newSensor(clazz, config.getSensor().getName(), config.getDescription()); - entity.sensors().set(attribute, null); - } - } - - @Override - public void onException(Exception exception) { - log.error("Detected exception while retrieving Windows Performance Counters from entity " + - entity.getDisplayName(), exception); - for (WindowsPerformanceCounterPollConfig<?> config : polls) { - entity.sensors().set(Sensors.newSensor(config.getSensor().getClass(), config.getPerformanceCounterName(), config.getDescription()), null); - } - } - - @Override - public String getDescription() { - return "" + polls; - } - - @Override - public String toString() { - return super.toString()+"["+getDescription()+"]"; - } - - private WindowsPerformanceCounterPollConfig<?> getPollConfig(String sensorName) { - for (WindowsPerformanceCounterPollConfig<?> poll : polls) { - if (poll.getPerformanceCounterName().equalsIgnoreCase(sensorName)) { - return poll; - } - } - throw new IllegalStateException(String.format("%s not found in configured polls: %s", sensorName, polls)); - } - } - - static class PerfCounterValueIterator implements Iterator<String> { - - // This pattern matches the contents of the first field, and optionally matches the rest of the line as - // further fields. Feed the second match back into the pattern again to get the next field, and repeat until - // all fields are discovered. - protected static final Pattern splitPerfData = Pattern.compile("^\"([^\\\"]*)\"((,\"[^\\\"]*\")*)$"); - - private Matcher matcher; - - public PerfCounterValueIterator(String input) { - matcher = splitPerfData.matcher(input); - // Throw away the first element (the timestamp) (and also confirm that we have a pattern match) - checkArgument(hasNext(), "input "+input+" does not match expected pattern "+splitPerfData.pattern()); - next(); - } - - @Override - public boolean hasNext() { - return matcher != null && matcher.find(); - } - - @Override - public String next() { - String next = matcher.group(1); - - String remainder = matcher.group(2); - if (!Strings.isNullOrEmpty(remainder)) { - assert remainder.startsWith(","); - remainder = remainder.substring(1); - matcher = splitPerfData.matcher(remainder); - } else { - matcher = null; - } - - return next; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - private static enum QuoteStringFunction implements Function<String, String> { - INSTANCE; - - @Nullable - @Override - public String apply(@Nullable String input) { - return input != null ? "\"" + input + "\"" : null; - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/main/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicy.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicy.java b/core/src/main/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicy.java deleted file mode 100644 index 5d3a0c8..0000000 --- a/core/src/main/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicy.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.entity.Entity; -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.api.sensor.SensorEvent; -import org.apache.brooklyn.api.sensor.SensorEventListener; -import org.apache.brooklyn.core.entity.AbstractEntity; -import org.apache.brooklyn.core.policy.AbstractPolicy; -import org.apache.brooklyn.core.sensor.Sensors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.annotations.Beta; - -/** - * When attached to an entity, this will monitor for when an {@link WinRmMachineLocation} is added to that entity - * (e.g. when a VM has been provisioned for it). - * - * The policy will then add a sensor that advertises the Administrator login details. - * - * A preferred mechanism would be for an external key-management tool to provide access to the credentials. - */ -@Beta -public class AdvertiseWinrmLoginPolicy extends AbstractPolicy implements SensorEventListener<Location> { - - // TODO Would like support user-creation over WinRM - - private static final Logger LOG = LoggerFactory.getLogger(AdvertiseWinrmLoginPolicy.class); - - public static final AttributeSensor<String> VM_USER_CREDENTIALS = Sensors.newStringSensor( - "vm.user.credentials", - "The \"<user> : <password> @ <hostname>:<port>\""); - - public void setEntity(EntityLocal entity) { - super.setEntity(entity); - subscriptions().subscribe(entity, AbstractEntity.LOCATION_ADDED, this); - } - - @Override - public void onEvent(SensorEvent<Location> event) { - final Entity entity = event.getSource(); - final Location loc = event.getValue(); - if (loc instanceof WinRmMachineLocation) { - advertiseUserAsync(entity, (WinRmMachineLocation)loc); - } - } - - protected void advertiseUserAsync(final Entity entity, final WinRmMachineLocation machine) { - String user = machine.getUser(); - String hostname = machine.getHostname(); - int port = machine.config().get(WinRmMachineLocation.WINRM_PORT); - String password = machine.config().get(WinRmMachineLocation.PASSWORD); - - String creds = user + " : " + password + " @ " +hostname + ":" + port; - - LOG.info("Advertising user "+user+" @ "+hostname+":"+port); - - ((EntityLocal)entity).sensors().set(VM_USER_CREDENTIALS, creds); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java b/core/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java deleted file mode 100644 index 3a7dbd5..0000000 --- a/core/src/main/java/org/apache/brooklyn/location/winrm/WinRmMachineLocation.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * 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 static com.google.common.base.Preconditions.checkNotNull; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.annotation.Nullable; - -import org.apache.brooklyn.api.location.MachineDetails; -import org.apache.brooklyn.api.location.MachineLocation; -import org.apache.brooklyn.api.location.OsDetails; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.location.AbstractLocation; -import org.apache.brooklyn.core.location.access.PortForwardManager; -import org.apache.commons.codec.binary.Base64; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Charsets; -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.net.HostAndPort; -import com.google.common.reflect.TypeToken; - -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.stream.Streams; -import org.apache.brooklyn.util.time.Duration; -import org.apache.brooklyn.util.time.Time; - -import io.cloudsoft.winrm4j.winrm.WinRmTool; -import io.cloudsoft.winrm4j.winrm.WinRmToolResponse; - -public class WinRmMachineLocation extends AbstractLocation implements MachineLocation { - - private static final Logger LOG = LoggerFactory.getLogger(WinRmMachineLocation.class); - - // FIXME Respect `port` config when using {@link WinRmTool} - public static final ConfigKey<Integer> WINRM_PORT = ConfigKeys.newIntegerConfigKey( - "port", - "WinRM port to use when connecting to the remote machine", - 5985); - - // TODO merge with {link SshTool#PROP_USER} and {@link SshMachineLocation#user} - public static final ConfigKey<String> USER = ConfigKeys.newStringConfigKey("user", - "Username to use when connecting to the remote machine"); - - // TODO merge with {link SshTool#PROP_PASSWORD} - public static final ConfigKey<String> PASSWORD = ConfigKeys.newStringConfigKey("password", - "Password to use when connecting to the remote machine"); - - public static final ConfigKey<Integer> COPY_FILE_CHUNK_SIZE_BYTES = ConfigKeys.newIntegerConfigKey("windows.copy.file.size.bytes", - "Size of file chunks (in bytes) to be used when copying a file to the remote server", 1024); - - public static final ConfigKey<InetAddress> ADDRESS = ConfigKeys.newConfigKey( - InetAddress.class, - "address", - "Address of the remote machine"); - - public static final ConfigKey<Integer> EXECUTION_ATTEMPTS = ConfigKeys.newIntegerConfigKey( - "windows.exec.attempts", - "Number of attempts to execute a remote command", - 1); - - // TODO See SshTool#PROP_SSH_TRIES, where it was called "sshTries"; remove duplication? Merge into one well-named thing? - public static final ConfigKey<Integer> EXEC_TRIES = ConfigKeys.newIntegerConfigKey( - "execTries", - "Max number of times to attempt WinRM operations", - 10); - - public static final ConfigKey<Iterable<String>> PRIVATE_ADDRESSES = ConfigKeys.newConfigKey( - new TypeToken<Iterable<String>>() {}, - "privateAddresses", - "Private addresses of this machine, e.g. those within the private network", - null); - - public static final ConfigKey<Map<Integer, String>> TCP_PORT_MAPPINGS = ConfigKeys.newConfigKey( - new TypeToken<Map<Integer, String>>() {}, - "tcpPortMappings", - "NAT'ed ports, giving the mapping from private TCP port to a public host:port", - null); - - @Override - public InetAddress getAddress() { - return getConfig(ADDRESS); - } - - @Override - public OsDetails getOsDetails() { - return null; - } - - @Override - public MachineDetails getMachineDetails() { - return null; - } - - @Nullable - @Override - public String getHostname() { - InetAddress address = getAddress(); - return (address != null) ? address.getHostAddress() : null; - } - - @Nullable - protected String getHostAndPort() { - String host = getHostname(); - return (host == null) ? null : host + ":" + config().get(WINRM_PORT); - } - - @Override - public Set<String> getPublicAddresses() { - InetAddress address = getAddress(); - return (address == null) ? ImmutableSet.<String>of() : ImmutableSet.of(address.getHostAddress()); - } - - @Override - public Set<String> getPrivateAddresses() { - Iterable<String> result = getConfig(PRIVATE_ADDRESSES); - return (result == null) ? ImmutableSet.<String>of() : ImmutableSet.copyOf(result); - } - - public WinRmToolResponse executeScript(String script) { - return executeScript(ImmutableList.of(script)); - } - - public WinRmToolResponse executeScript(List<String> script) { - int execTries = getRequiredConfig(EXEC_TRIES); - Collection<Throwable> exceptions = Lists.newArrayList(); - for (int i = 0; i < execTries; i++) { - try { - return executeScriptNoRetry(script); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - if (i == (execTries+1)) { - LOG.info("Propagating WinRM exception (attempt "+(i+1)+" of "+execTries+")", e); - } else if (i == 0) { - LOG.warn("Ignoring WinRM exception and retrying (attempt "+(i+1)+" of "+execTries+")", e); - } else { - LOG.debug("Ignoring WinRM exception and retrying (attempt "+(i+1)+" of "+execTries+")", e); - } - exceptions.add(e); - } - } - throw Exceptions.propagate("failed to execute shell script", exceptions); - } - - protected WinRmToolResponse executeScriptNoRetry(List<String> script) { - WinRmTool winRmTool = WinRmTool.connect(getHostAndPort(), getUser(), getPassword()); - WinRmToolResponse response = winRmTool.executeScript(script); - return response; - } - - public WinRmToolResponse executePsScript(String psScript) { - return executePsScript(ImmutableList.of(psScript)); - } - - public WinRmToolResponse executePsScript(List<String> psScript) { - int execTries = getRequiredConfig(EXEC_TRIES); - Collection<Throwable> exceptions = Lists.newArrayList(); - for (int i = 0; i < execTries; i++) { - try { - return executePsScriptNoRetry(psScript); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - if (i == (execTries+1)) { - LOG.info("Propagating WinRM exception (attempt "+(i+1)+" of "+execTries+")", e); - } else if (i == 0) { - LOG.warn("Ignoring WinRM exception and retrying after 5 seconds (attempt "+(i+1)+" of "+execTries+")", e); - Time.sleep(Duration.FIVE_SECONDS); - } else { - LOG.debug("Ignoring WinRM exception and retrying after 5 seconds (attempt "+(i+1)+" of "+execTries+")", e); - Time.sleep(Duration.FIVE_SECONDS); - } - exceptions.add(e); - } - } - throw Exceptions.propagate("failed to execute powershell script", exceptions); - } - - public WinRmToolResponse executePsScriptNoRetry(List<String> psScript) { - WinRmTool winRmTool = WinRmTool.connect(getHostAndPort(), getUser(), getPassword()); - WinRmToolResponse response = winRmTool.executePs(psScript); - return response; - } - - public int copyTo(File source, String destination) { - FileInputStream sourceStream = null; - try { - sourceStream = new FileInputStream(source); - return copyTo(sourceStream, destination); - } catch (FileNotFoundException e) { - throw Exceptions.propagate(e); - } finally { - if (sourceStream != null) { - Streams.closeQuietly(sourceStream); - } - } - } - - public int copyTo(InputStream source, String destination) { - executePsScript(ImmutableList.of("rm -ErrorAction SilentlyContinue " + destination)); - try { - int chunkSize = getConfig(COPY_FILE_CHUNK_SIZE_BYTES); - byte[] inputData = new byte[chunkSize]; - int bytesRead; - int expectedFileSize = 0; - while ((bytesRead = source.read(inputData)) > 0) { - byte[] chunk; - if (bytesRead == chunkSize) { - chunk = inputData; - } else { - chunk = Arrays.copyOf(inputData, bytesRead); - } - executePsScript(ImmutableList.of("If ((!(Test-Path " + destination + ")) -or ((Get-Item '" + destination + "').length -eq " + - expectedFileSize + ")) {Add-Content -Encoding Byte -path " + destination + - " -value ([System.Convert]::FromBase64String(\"" + new String(Base64.encodeBase64(chunk)) + "\"))}")); - expectedFileSize += bytesRead; - } - - return 0; - } catch (java.io.IOException e) { - throw Exceptions.propagate(e); - } - } - - @Override - public void init() { - super.init(); - - // Register any pre-existing port-mappings with the PortForwardManager - Map<Integer, String> tcpPortMappings = getConfig(TCP_PORT_MAPPINGS); - if (tcpPortMappings != null) { - PortForwardManager pfm = (PortForwardManager) getManagementContext().getLocationRegistry().resolve("portForwardManager(scope=global)"); - for (Map.Entry<Integer, String> entry : tcpPortMappings.entrySet()) { - int targetPort = entry.getKey(); - HostAndPort publicEndpoint = HostAndPort.fromString(entry.getValue()); - if (!publicEndpoint.hasPort()) { - throw new IllegalArgumentException("Invalid portMapping ('"+entry.getValue()+"') for port "+targetPort+" in machine "+this); - } - pfm.associate(publicEndpoint.getHostText(), publicEndpoint, this, targetPort); - } - } - } - public String getUser() { - return config().get(USER); - } - - private String getPassword() { - return config().get(PASSWORD); - } - - private <T> T getRequiredConfig(ConfigKey<T> key) { - return checkNotNull(getConfig(key), "key %s must be set", key); - } - - public static String getDefaultUserMetadataString() { - // Using an encoded command obviates the need to escape - String unencodePowershell = Joiner.on("\r\n").join(ImmutableList.of( - // Allow TS connections - "$RDP = Get-WmiObject -Class Win32_TerminalServiceSetting -ComputerName $env:computername -Namespace root\\CIMV2\\TerminalServices -Authentication PacketPrivacy", - "$RDP.SetAllowTSConnections(1,1)", - "Set-ExecutionPolicy Unrestricted -Force", - // Set unlimited values for remote execution limits - "Set-Item WSMan:\\localhost\\Shell\\MaxConcurrentUsers 100", - "Set-Item WSMan:\\localhost\\Shell\\MaxMemoryPerShellMB 0", - "Set-Item WSMan:\\localhost\\Shell\\MaxProcessesPerShell 0", - "Set-Item WSMan:\\localhost\\Shell\\MaxShellsPerUser 0", - "New-ItemProperty \"HKLM:\\System\\CurrentControlSet\\Control\\LSA\" -Name \"SuppressExtendedProtection\" -Value 1 -PropertyType \"DWord\"", - // The following allows scripts to re-authenticate with local credential - this is required - // as certain operations cannot be performed with remote credentials - "$allowed = @('WSMAN/*')", - "$key = 'hklm:\\SOFTWARE\\Policies\\Microsoft\\Windows\\CredentialsDelegation'", - "if (!(Test-Path $key)) {", - " md $key", - "}", - "New-ItemProperty -Path $key -Name AllowFreshCredentials -Value 1 -PropertyType Dword -Force", - "New-ItemProperty -Path $key -Name AllowFreshCredentialsWhenNTLMOnly -Value 1 -PropertyType Dword -Force", - "$credKey = Join-Path $key 'AllowFreshCredentials'", - "if (!(Test-Path $credKey)) {", - " md $credkey", - "}", - "$ntlmKey = Join-Path $key 'AllowFreshCredentialsWhenNTLMOnly'", - "if (!(Test-Path $ntlmKey)) {", - " md $ntlmKey", - "}", - "$i = 1", - "$allowed |% {", - " # Script does not take into account existing entries in this key", - " New-ItemProperty -Path $credKey -Name $i -Value $_ -PropertyType String -Force", - " New-ItemProperty -Path $ntlmKey -Name $i -Value $_ -PropertyType String -Force", - " $i++", - "}" - )); - - String encoded = new String(Base64.encodeBase64(unencodePowershell.getBytes(Charsets.UTF_16LE))); - return "winrm quickconfig -q & " + - "winrm set winrm/config/service/auth @{Basic=\"true\"} & " + - "winrm set winrm/config/service/auth @{CredSSP=\"true\"} & " + - "winrm set winrm/config/client/auth @{CredSSP=\"true\"} & " + - "winrm set winrm/config/client @{AllowUnencrypted=\"true\"} & " + - "winrm set winrm/config/service @{AllowUnencrypted=\"true\"} & " + - "winrm set winrm/config/winrs @{MaxConcurrentUsers=\"100\"} & " + - "winrm set winrm/config/winrs @{MaxMemoryPerShellMB=\"0\"} & " + - "winrm set winrm/config/winrs @{MaxProcessesPerShell=\"0\"} & " + - "winrm set winrm/config/winrs @{MaxShellsPerUser=\"0\"} & " + - "netsh advfirewall firewall add rule name=RDP dir=in protocol=tcp localport=3389 action=allow profile=any & " + - "netsh advfirewall firewall add rule name=WinRM dir=in protocol=tcp localport=5985 action=allow profile=any & " + - "powershell -EncodedCommand " + encoded; - /* TODO: Find out why scripts with new line characters aren't working on AWS. The following appears as if it *should* - work but doesn't - the script simply isn't run. By connecting to the machine via RDP, you can get the script - from 'http://169.254.169.254/latest/user-data', and running it at the command prompt works, but for some - reason the script isn't run when the VM is provisioned - */ -// return Joiner.on("\r\n").join(ImmutableList.of( -// "winrm quickconfig -q", -// "winrm set winrm/config/service/auth @{Basic=\"true\"}", -// "winrm set winrm/config/client @{AllowUnencrypted=\"true\"}", -// "winrm set winrm/config/service @{AllowUnencrypted=\"true\"}", -// "netsh advfirewall firewall add rule name=RDP dir=in protocol=tcp localport=3389 action=allow profile=any", -// "netsh advfirewall firewall add rule name=WinRM dir=in protocol=tcp localport=5985 action=allow profile=any", -// // Using an encoded command necessitates the need to escape. The unencoded command is as follows: -// // $RDP = Get-WmiObject -Class Win32_TerminalServiceSetting -ComputerName $env:computername -Namespace root\CIMV2\TerminalServices -Authentication PacketPrivacy -// // $Result = $RDP.SetAllowTSConnections(1,1) -// "powershell -EncodedCommand JABSAEQAUAAgAD0AIABHAGUAdAAtAFcAbQBpAE8AYgBqAGUAYwB0ACAALQBDAGwAYQBzAHMAI" + -// "ABXAGkAbgAzADIAXwBUAGUAcgBtAGkAbgBhAGwAUwBlAHIAdgBpAGMAZQBTAGUAdAB0AGkAbgBnACAALQBDAG8AbQBwA" + -// "HUAdABlAHIATgBhAG0AZQAgACQAZQBuAHYAOgBjAG8AbQBwAHUAdABlAHIAbgBhAG0AZQAgAC0ATgBhAG0AZQBzAHAAY" + -// "QBjAGUAIAByAG8AbwB0AFwAQwBJAE0AVgAyAFwAVABlAHIAbQBpAG4AYQBsAFMAZQByAHYAaQBjAGUAcwAgAC0AQQB1A" + -// "HQAaABlAG4AdABpAGMAYQB0AGkAbwBuACAAUABhAGMAawBlAHQAUAByAGkAdgBhAGMAeQANAAoAJABSAGUAcwB1AGwAd" + -// "AAgAD0AIAAkAFIARABQAC4AUwBlAHQAQQBsAGwAbwB3AFQAUwBDAG8AbgBuAGUAYwB0AGkAbwBuAHMAKAAxACwAMQApAA==" -// )); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java index d6528df..19a6ba4 100644 --- a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java @@ -26,7 +26,7 @@ import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.mgmt.EntityManagementUtils; import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; -import org.python.google.common.collect.Iterables; +import com.google.common.collect.Iterables; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/test/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeedLiveTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeedLiveTest.java b/core/src/test/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeedLiveTest.java deleted file mode 100644 index 9ef9ade..0000000 --- a/core/src/test/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeedLiveTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.feed.windows; - -import java.util.Map; - -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.location.MachineLocation; -import org.apache.brooklyn.api.location.MachineProvisioningLocation; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.core.sensor.Sensors; -import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport; -import org.apache.brooklyn.core.test.entity.TestEntity; -import org.apache.brooklyn.feed.windows.WindowsPerformanceCounterFeed; -import org.apache.brooklyn.test.EntityTestUtils; -import org.apache.brooklyn.util.collections.MutableMap; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; - -/** - * WindowsPerformanceCounterFeed Live Test. - * <p> - * This test is currently disabled. To run, you must configure a location named {@code WindowsLiveTest} - * or adapt the {@link #LOCATION_SPEC} below. - * <p> - * The location must provide Windows nodes that are running an SSH server on port 22. The login credentials must - * be either be auto-detectable or configured in brooklyn.properties in the usual fashion. - * <p> - * Here is an example configuration from brooklyn.properties for a pre-configured Windows VM - * running an SSH server with public key authentication: - * <pre> - * {@code brooklyn.location.named.WindowsLiveTest=byon:(hosts="ec2-xx-xxx-xxx-xx.eu-west-1.compute.amazonaws.com") - * brooklyn.location.named.WindowsLiveTest.user=Administrator - * brooklyn.location.named.WindowsLiveTest.privateKeyFile = ~/.ssh/id_rsa - * brooklyn.location.named.WindowsLiveTest.publicKeyFile = ~/.ssh/id_rsa.pub - * }</pre> - * The location must by {@code byon} or another primitive type. Unfortunately, it's not possible to - * use a jclouds location, as adding a dependency on brooklyn-locations-jclouds would cause a - * cyclic dependency. - */ -public class WindowsPerformanceCounterFeedLiveTest extends BrooklynAppLiveTestSupport { - - final static AttributeSensor<Double> CPU_IDLE_TIME = Sensors.newDoubleSensor("cpu.idleTime", ""); - final static AttributeSensor<Integer> TELEPHONE_LINES = Sensors.newIntegerSensor("telephone.lines", ""); - - private static final String LOCATION_SPEC = "named:WindowsLiveTest"; - - private Location loc; - private EntityLocal entity; - - @BeforeMethod(alwaysRun=true) - public void setUp() throws Exception { - super.setUp(); - - Map<String,?> allFlags = MutableMap.<String,Object>builder() - .put("tags", ImmutableList.of(getClass().getName())) - .build(); - MachineProvisioningLocation<? extends MachineLocation> provisioningLocation = - (MachineProvisioningLocation<? extends MachineLocation>) - mgmt.getLocationRegistry().resolve(LOCATION_SPEC, allFlags); - loc = provisioningLocation.obtain(ImmutableMap.of()); - - entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - app.start(ImmutableList.of(loc)); - } - - @Test(groups={"Live","Disabled"}, enabled=false) - public void testRetrievesPerformanceCounters() throws Exception { - // We can be pretty sure that a Windows instance in the cloud will have zero telephone lines... - entity.sensors().set(TELEPHONE_LINES, 42); - WindowsPerformanceCounterFeed feed = WindowsPerformanceCounterFeed.builder() - .entity(entity) - .addSensor("\\Processor(_total)\\% Idle Time", CPU_IDLE_TIME) - .addSensor("\\Telephony\\Lines", TELEPHONE_LINES) - .build(); - try { - EntityTestUtils.assertAttributeEqualsEventually(entity, TELEPHONE_LINES, 0); - } finally { - feed.stop(); - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/test/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeedTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeedTest.java b/core/src/test/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeedTest.java deleted file mode 100644 index 3f4862b..0000000 --- a/core/src/test/java/org/apache/brooklyn/feed/windows/WindowsPerformanceCounterFeedTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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.feed.windows; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; - -import java.util.Collection; -import java.util.Iterator; - -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.core.sensor.Sensors; -import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; -import org.apache.brooklyn.core.test.entity.TestEntity; -import org.apache.brooklyn.feed.windows.WindowsPerformanceCounterFeed; -import org.apache.brooklyn.feed.windows.WindowsPerformanceCounterPollConfig; -import org.apache.brooklyn.test.EntityTestUtils; -import org.apache.brooklyn.util.text.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; -import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; - -import io.cloudsoft.winrm4j.winrm.WinRmToolResponse; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -public class WindowsPerformanceCounterFeedTest extends BrooklynAppUnitTestSupport { - - private Location loc; - private EntityLocal entity; - - @BeforeMethod(alwaysRun=true) - @Override - public void setUp() throws Exception { - super.setUp(); - loc = new LocalhostMachineProvisioningLocation(); - entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - app.start(ImmutableList.of(loc)); - } - - @AfterMethod(alwaysRun=true) - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - - private static final Logger log = LoggerFactory.getLogger(WindowsPerformanceCounterFeedTest.class); - - @Test - public void testIteratorWithSingleValue() { - Iterator<?> iterator = new WindowsPerformanceCounterFeed - .PerfCounterValueIterator("\"10/14/2013 15:28:24.406\",\"0.000000\""); - assertTrue(iterator.hasNext()); - assertEquals(iterator.next(), "0.000000"); - assertFalse(iterator.hasNext()); - } - - @Test - public void testIteratorWithMultipleValues() { - Iterator<?> iterator = new WindowsPerformanceCounterFeed - .PerfCounterValueIterator("\"10/14/2013 15:35:50.582\",\"8803.000000\",\"405622.000000\""); - assertTrue(iterator.hasNext()); - assertEquals(iterator.next(), "8803.000000"); - assertTrue(iterator.hasNext()); - assertEquals(iterator.next(), "405622.000000"); - assertFalse(iterator.hasNext()); - } - - @Test - public void testSendPerfCountersToSensors() { - AttributeSensor<String> stringSensor = Sensors.newStringSensor("foo.bar"); - AttributeSensor<Integer> integerSensor = Sensors.newIntegerSensor("bar.baz"); - AttributeSensor<Double> doubleSensor = Sensors.newDoubleSensor("baz.quux"); - - Collection<WindowsPerformanceCounterPollConfig<?>> polls = ImmutableSet.<WindowsPerformanceCounterPollConfig<?>>of( - new WindowsPerformanceCounterPollConfig(stringSensor).performanceCounterName("\\processor information(_total)\\% processor time"), - new WindowsPerformanceCounterPollConfig(integerSensor).performanceCounterName("\\integer.sensor"), - new WindowsPerformanceCounterPollConfig(doubleSensor).performanceCounterName("\\double\\sensor\\with\\multiple\\sub\\paths") - ); - - WindowsPerformanceCounterFeed.SendPerfCountersToSensors sendPerfCountersToSensors = new WindowsPerformanceCounterFeed.SendPerfCountersToSensors(entity, polls); - - assertNull(entity.getAttribute(stringSensor)); - - StringBuilder responseBuilder = new StringBuilder(); - // NOTE: This builds the response in a different order to which they are passed to the SendPerfCountersToSensors constructor - // this tests that the values are applied correctly even if the (possibly non-deterministic) order in which - // they are returned by the Get-Counter scriptlet is different - addMockResponse(responseBuilder, "\\\\machine.name\\double\\sensor\\with\\multiple\\sub\\paths", "3.1415926"); - addMockResponse(responseBuilder, "\\\\win-lge7uj2blau\\processor information(_total)\\% processor time", "99.9"); - addMockResponse(responseBuilder, "\\\\machine.name\\integer.sensor", "15"); - - sendPerfCountersToSensors.onSuccess(new WinRmToolResponse(responseBuilder.toString(), "", 0)); - - EntityTestUtils.assertAttributeEquals(entity, stringSensor, "99.9"); - EntityTestUtils.assertAttributeEquals(entity, integerSensor, 15); - EntityTestUtils.assertAttributeEquals(entity, doubleSensor, 3.1415926); - } - - private void addMockResponse(StringBuilder responseBuilder, String path, String value) { - responseBuilder.append(path); - responseBuilder.append(Strings.repeat(" ", 200 - (path.length() + value.length()))); - responseBuilder.append(value); - responseBuilder.append("\r\n"); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/test/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicyTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicyTest.java b/core/src/test/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicyTest.java deleted file mode 100644 index 65ac92e..0000000 --- a/core/src/test/java/org/apache/brooklyn/location/winrm/AdvertiseWinrmLoginPolicyTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.entity.EntitySpec; -import org.apache.brooklyn.api.location.LocationSpec; -import org.apache.brooklyn.api.policy.PolicySpec; -import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; -import org.apache.brooklyn.core.test.entity.TestEntity; -import org.apache.brooklyn.test.EntityTestUtils; -import org.testng.annotations.Test; -import org.apache.brooklyn.location.winrm.AdvertiseWinrmLoginPolicy; -import org.apache.brooklyn.location.winrm.WinRmMachineLocation; - -import com.google.common.collect.ImmutableList; - -public class AdvertiseWinrmLoginPolicyTest extends BrooklynAppUnitTestSupport { - - @Test - public void testAdvertisesMachineLoginDetails() throws Exception { - TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class) - .policy(PolicySpec.create(AdvertiseWinrmLoginPolicy.class))); - - WinRmMachineLocation machine = mgmt.getLocationManager().createLocation(LocationSpec.create(WinRmMachineLocation.class) - .configure("address", "1.2.3.4") - .configure("user", "myuser") - .configure("port", 5678) - .configure("password", "mypassword")); - app.start(ImmutableList.of(machine)); - - String expected = "myuser : mypassword @ 1.2.3.4:5678"; - - EntityTestUtils.assertAttributeEqualsEventually(entity, AdvertiseWinrmLoginPolicy.VM_USER_CREDENTIALS, expected); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/core/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java deleted file mode 100644 index f7f7fc1..0000000 --- a/core/src/test/java/org/apache/brooklyn/location/winrm/WinRmMachineLocationTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 static org.testng.Assert.assertEquals; - -import org.apache.brooklyn.api.location.LocationSpec; -import org.apache.brooklyn.core.entity.BrooklynConfigKeys; -import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; -import org.apache.brooklyn.location.winrm.WinRmMachineLocation; -import org.apache.brooklyn.util.net.Networking; -import org.testng.annotations.Test; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - -public class WinRmMachineLocationTest extends BrooklynAppUnitTestSupport { - - @Test - public void testConfigurePrivateAddresses() throws Exception { - WinRmMachineLocation host = mgmt.getLocationManager().createLocation(LocationSpec.create(WinRmMachineLocation.class) - .configure("address", Networking.getLocalHost()) - .configure(WinRmMachineLocation.PRIVATE_ADDRESSES, ImmutableList.of("1.2.3.4")) - .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true)); - - assertEquals(host.getPrivateAddresses(), ImmutableSet.of("1.2.3.4")); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 560dcd8..8e4c265 100644 --- a/pom.xml +++ b/pom.xml @@ -108,6 +108,7 @@ <module>software/nosql</module> <module>software/database</module> <module>software/monitoring</module> + <module>software/winrm</module> <module>storage/hazelcast</module> http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/software/winrm/pom.xml ---------------------------------------------------------------------- diff --git a/software/winrm/pom.xml b/software/winrm/pom.xml new file mode 100644 index 0000000..77d2fa6 --- /dev/null +++ b/software/winrm/pom.xml @@ -0,0 +1,45 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-parent</artifactId> + <version>0.9.0-SNAPSHOT</version> <!-- BROOKLYN_VERSION --> + <relativePath>../../parent/pom.xml</relativePath> + </parent> + + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-software-winrm</artifactId> + + <name>Brooklyn WinRM Software Entities</name> + + <dependencies> + <dependency> + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>io.cloudsoft.windows</groupId> + <artifactId>winrm4j</artifactId> + <version>${winrm4j.version}</version> + </dependency> + + <!-- test --> + <dependency> + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-core</artifactId> + <version>${project.version}</version> + <classifier>tests</classifier> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-test-support</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/8fa4df7d/software/winrm/src/main/java/org/apache/brooklyn/core/sensor/windows/WindowsPerformanceCounterSensors.java ---------------------------------------------------------------------- diff --git a/software/winrm/src/main/java/org/apache/brooklyn/core/sensor/windows/WindowsPerformanceCounterSensors.java b/software/winrm/src/main/java/org/apache/brooklyn/core/sensor/windows/WindowsPerformanceCounterSensors.java new file mode 100644 index 0000000..f5c2271 --- /dev/null +++ b/software/winrm/src/main/java/org/apache/brooklyn/core/sensor/windows/WindowsPerformanceCounterSensors.java @@ -0,0 +1,73 @@ +/* + * 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.core.sensor.windows; + +import java.util.Map; +import java.util.Set; + +import org.apache.brooklyn.api.entity.EntityInitializer; +import org.apache.brooklyn.api.entity.EntityLocal; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.entity.EntityInternal; +import org.apache.brooklyn.core.sensor.Sensors; +import org.apache.brooklyn.feed.windows.WindowsPerformanceCounterFeed; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.text.Strings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.reflect.TypeToken; + +public class WindowsPerformanceCounterSensors implements EntityInitializer { + + private static final Logger LOG = LoggerFactory.getLogger(WindowsPerformanceCounterSensors.class); + + public final static ConfigKey<Set<Map<String, String>>> PERFORMANCE_COUNTERS = ConfigKeys.newConfigKey(new TypeToken<Set<Map<String, String>>>(){}, "performance.counters"); + + protected final Set<Map<String, String>> sensors; + + public WindowsPerformanceCounterSensors(ConfigBag params) { + sensors = params.get(PERFORMANCE_COUNTERS); + } + + public WindowsPerformanceCounterSensors(Map<String, String> params) { + this(ConfigBag.newInstance(params)); + } + + @Override + public void apply(EntityLocal entity) { + WindowsPerformanceCounterFeed.Builder builder = WindowsPerformanceCounterFeed.builder() + .entity(entity); + for (Map<String, String> sensorConfig : sensors) { + String name = sensorConfig.get("name"); + String sensorType = sensorConfig.get("sensorType"); + Class<?> clazz; + try { + clazz = Strings.isNonEmpty(sensorType) + ? ((EntityInternal)entity).getManagementContext().getCatalog().getRootClassLoader().loadClass(sensorType) + : String.class; + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Could not load type "+sensorType+" for sensor "+name, e); + } + builder.addSensor(sensorConfig.get("counter"), Sensors.newSensor(clazz, name, sensorConfig.get("description"))); + } + builder.build(); + } +}
