You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/14 05:42:47 UTC

[18/54] incubator-brooklyn git commit: [BROOKLYN-162] Renaming package brooklyn.location

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsWinRmMachineLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsWinRmMachineLocation.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsWinRmMachineLocation.java
deleted file mode 100644
index d555cd9..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsWinRmMachineLocation.java
+++ /dev/null
@@ -1,154 +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 brooklyn.location.jclouds;
-
-import static brooklyn.util.JavaGroovyEquivalents.groovyTruth;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.Template;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.location.basic.WinRmMachineLocation;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.net.Networking;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.net.HostAndPort;
-
-public class JcloudsWinRmMachineLocation extends WinRmMachineLocation implements JcloudsMachineLocation {
-
-    private static final Logger LOG = LoggerFactory.getLogger(JcloudsWinRmMachineLocation.class);
-
-    @SetFromFlag
-    JcloudsLocation jcloudsParent;
-    
-    @SetFromFlag
-    NodeMetadata node;
-    
-    @SetFromFlag
-    Template template;
-
-    public JcloudsWinRmMachineLocation() {
-    }
-
-    @Override
-    public String toVerboseString() {
-        return Objects.toStringHelper(this).omitNullValues()
-                .add("id", getId()).add("name", getDisplayName())
-                .add("user", getUser())
-                .add("address", getAddress())
-                .add("port", getPort())
-                .add("node", getNode())
-                .add("jcloudsId", getJcloudsId())
-                .add("privateAddresses", node.getPrivateAddresses())
-                .add("publicAddresses", node.getPublicAddresses())
-                .add("parentLocation", getParent())
-                .add("osDetails", getOsDetails())
-                .toString();
-    }
-
-    @Override
-    public int getPort() {
-        return getConfig(WINRM_PORT);
-    }
-    
-    @Override
-    public NodeMetadata getNode() {
-        return node;
-    }
-    
-    @Override
-    public Template getTemplate() {
-        return template;
-    }
-    
-    @Override
-    public JcloudsLocation getParent() {
-        return jcloudsParent;
-    }
-    
-    @Override
-    public String getHostname() {
-        InetAddress address = getAddress();
-        return (address != null) ? address.getHostAddress() : null;
-    }
-    
-    @Override
-    public Set<String> getPublicAddresses() {
-        return node.getPublicAddresses();
-    }
-    
-    @Override
-    public Set<String> getPrivateAddresses() {
-        return node.getPrivateAddresses();
-    }
-
-    @Override
-    public String getSubnetHostname() {
-        // TODO: TEMP FIX: WAS:
-        // String publicHostname = jcloudsParent.getPublicHostname(node, Optional.<HostAndPort>absent(), config().getBag());
-        // but this causes a call to JcloudsUtil.getFirstReachableAddress, which searches for accessible SSH service.
-        // This workaround is good for public nodes but not private-subnet ones.
-        return getHostname();
-    }
-
-    @Override
-    public String getSubnetIp() {
-        Optional<String> privateAddress = getPrivateAddress();
-        if (privateAddress.isPresent()) {
-            return privateAddress.get();
-        }
-
-        String hostname = jcloudsParent.getPublicHostname(node, Optional.<HostAndPort>absent(), config().getBag());
-        if (hostname != null && !Networking.isValidIp4(hostname)) {
-            try {
-                return InetAddress.getByName(hostname).getHostAddress();
-            } catch (UnknownHostException e) {
-                LOG.debug("Cannot resolve IP for hostname {} of machine {} (so returning hostname): {}", new Object[] {hostname, this, e});
-            }
-        }
-        return hostname;
-    }
-
-    protected Optional<String> getPrivateAddress() {
-        if (groovyTruth(node.getPrivateAddresses())) {
-            Iterator<String> pi = node.getPrivateAddresses().iterator();
-            while (pi.hasNext()) {
-                String p = pi.next();
-                // disallow local only addresses
-                if (Networking.isLocalOnly(p)) continue;
-                // other things may be public or private, but either way, return it
-                return Optional.of(p);
-            }
-        }
-        return Optional.absent();
-    }
-    
-    @Override
-    public String getJcloudsId() {
-        return node.getId();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/SudoTtyFixingCustomizer.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/SudoTtyFixingCustomizer.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/SudoTtyFixingCustomizer.java
deleted file mode 100644
index 889c7e3..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/SudoTtyFixingCustomizer.java
+++ /dev/null
@@ -1,58 +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 brooklyn.location.jclouds;
-
-import org.jclouds.compute.ComputeService;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.ssh.SshTasks;
-import brooklyn.util.task.ssh.SshTasks.OnFailingTask;
-
-/**
- * Wraps Brooklyn's sudo-tty mitigations in a {@link JcloudsLocationCustomizer} for easy(-ish) consumption
- * in YAML blueprints:
- *
- * <pre>
- *   name: My App
- *   brooklyn.config:
- *     provisioning.properties:
- *       customizerType: brooklyn.location.jclouds.SudoTtyFixingCustomizer
- *   services: ...
- * </pre>
- *
- * <p>This class should be seen as a temporary workaround and might disappear completely if/when Brooklyn takes care of this automatically.
- *
- * <p>See
- * <a href='http://unix.stackexchange.com/questions/122616/why-do-i-need-a-tty-to-run-sudo-if-i-can-sudo-without-a-password'>http://unix.stackexchange.com/questions/122616/why-do-i-need-a-tty-to-run-sudo-if-i-can-sudo-without-a-password</a>
- * for background.
- */
-@Beta
-public class SudoTtyFixingCustomizer extends BasicJcloudsLocationCustomizer {
-
-    @Override
-    public void customize(JcloudsLocation location, ComputeService computeService, JcloudsMachineLocation machine) {
-        Preconditions.checkArgument(machine instanceof SshMachineLocation, "machine must be SshMachineLocation, but is %s", machine.getClass());
-        DynamicTasks.queueIfPossible(SshTasks.dontRequireTtyForSudo((SshMachineLocation)machine, OnFailingTask.FAIL)).orSubmitAndBlock();
-        DynamicTasks.waitForLast();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
deleted file mode 100644
index 3944912..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/JcloudsLocationSecurityGroupCustomizer.java
+++ /dev/null
@@ -1,561 +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 brooklyn.location.jclouds.networking;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Iterator;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.jclouds.aws.AWSResponseException;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.domain.SecurityGroup;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.extensions.SecurityGroupExtension;
-import org.jclouds.domain.Location;
-import org.jclouds.net.domain.IpPermission;
-import org.jclouds.net.domain.IpProtocol;
-import org.jclouds.providers.ProviderMetadata;
-import org.jclouds.providers.Providers;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.location.geo.LocalhostExternalIpLoader;
-import brooklyn.location.jclouds.BasicJcloudsLocationCustomizer;
-import brooklyn.location.jclouds.JcloudsLocation;
-import brooklyn.location.jclouds.JcloudsMachineLocation;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.net.Cidr;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.base.Throwables;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-/**
- * Configures custom security groups on Jclouds locations.
- *
- * @see SecurityGroupExtension is an optional extension to jclouds compute service. It allows the manipulation of
- * {@link SecurityGroup}s.
- *
- * This customizer can be injected into {@link JcloudsLocation#obtainOnce} using
- * It will be executed after the provisiioning of the {@link JcloudsMachineLocation} to apply app-specific
- * customization related to the security groups.
- *
- * @since 0.7.0
- */
-@Beta
-public class JcloudsLocationSecurityGroupCustomizer extends BasicJcloudsLocationCustomizer {
-
-    private static final Logger LOG = LoggerFactory.getLogger(JcloudsLocationSecurityGroupCustomizer.class);
-
-    // Caches instances of JcloudsLocationSecurityGroupCustomizer by application IDs.
-    private static final LoadingCache<String, JcloudsLocationSecurityGroupCustomizer> CUSTOMISERS = CacheBuilder.newBuilder()
-            .build(new CacheLoader<String, JcloudsLocationSecurityGroupCustomizer>() {
-                @Override
-                public JcloudsLocationSecurityGroupCustomizer load(final String appContext) throws Exception {
-                    return new JcloudsLocationSecurityGroupCustomizer(appContext);
-                }
-            });
-
-    /** Caches the base security group that should be shared between all instances in the same Jclouds location */
-    private final Cache<Location, SecurityGroup> sharedGroupCache = CacheBuilder.newBuilder().build();
-
-    /** Caches security groups unique to instances */
-    private final Cache<String, SecurityGroup> uniqueGroupCache = CacheBuilder.newBuilder().build();
-
-    /** The context for this location customizer. */
-    private final String applicationId;
-
-    /** The CIDR for addresses that may SSH to machines. */
-    private Supplier<Cidr> sshCidrSupplier;
-
-    /**
-     * A predicate indicating whether the customiser can retry a request to add a security group
-     * or a rule after an throwable is thrown.
-     */
-    private Predicate<Exception> isExceptionRetryable = Predicates.alwaysFalse();
-
-    protected JcloudsLocationSecurityGroupCustomizer(String applicationId) {
-        // Would be better to restrict with something like LocalhostExternalIpCidrSupplier, but
-        // we risk making machines inaccessible from Brooklyn when HA fails over.
-        this(applicationId, Suppliers.ofInstance(new Cidr("0.0.0.0/0")));
-    }
-
-    protected JcloudsLocationSecurityGroupCustomizer(String applicationId, Supplier<Cidr> sshCidrSupplier) {
-        this.applicationId = applicationId;
-        this.sshCidrSupplier = sshCidrSupplier;
-    }
-
-    /**
-     * Gets the customizer for the given applicationId. Multiple calls to this method with the
-     * same application context will return the same JcloudsLocationSecurityGroupCustomizer instance.
-     * @param applicationId An identifier for the application the customizer is to be used for
-     * @return the unique customizer for the given context
-     */
-    public static JcloudsLocationSecurityGroupCustomizer getInstance(String applicationId) {
-        return CUSTOMISERS.getUnchecked(applicationId);
-    }
-
-    /**
-     * Gets a customizer for the given entity's application. Multiple calls to this method with entities
-     * in the same application will return the same JcloudsLocationSecurityGroupCustomizer instance.
-     * @param entity The entity the customizer is to be used for
-     * @return the unique customizer for the entity's owning application
-     */
-    public static JcloudsLocationSecurityGroupCustomizer getInstance(Entity entity) {
-        return getInstance(entity.getApplicationId());
-    }
-
-    /**
-     * @param predicate
-     *          A predicate whose return value indicates whether a request to add a security group
-     *          or permission may be retried after its input {@link Exception} was thrown.
-     * @return this
-     */
-    public JcloudsLocationSecurityGroupCustomizer setRetryExceptionPredicate(Predicate<Exception> predicate) {
-        this.isExceptionRetryable = checkNotNull(predicate, "predicate");
-        return this;
-    }
-
-    /**
-     * @param cidrSupplier A supplier returning a CIDR for hosts that are allowed to SSH to locations.
-     */
-    public JcloudsLocationSecurityGroupCustomizer setSshCidrSupplier(Supplier<Cidr> cidrSupplier) {
-        this.sshCidrSupplier = checkNotNull(cidrSupplier, "cidrSupplier");
-        return this;
-    }
-
-    /** @see #addPermissionsToLocation(brooklyn.location.jclouds.JcloudsSshMachineLocation, java.lang.Iterable) */
-    public JcloudsLocationSecurityGroupCustomizer addPermissionsToLocation(final JcloudsMachineLocation location, IpPermission... permissions) {
-        addPermissionsToLocation(location, ImmutableList.copyOf(permissions));
-        return this;
-    }
-
-    /** @see #addPermissionsToLocation(brooklyn.location.jclouds.JcloudsSshMachineLocation, java.lang.Iterable) */
-    public JcloudsLocationSecurityGroupCustomizer addPermissionsToLocation(final JcloudsMachineLocation location, SecurityGroupDefinition securityGroupDefinition) {
-        addPermissionsToLocation(location, securityGroupDefinition.getPermissions());
-        return this;
-    }
-
-    /**
-     * Applies the given security group permissions to the given location.
-     * <p>
-     * Takes no action if the location's compute service does not have a security group extension.
-     * @param permissions The set of permissions to be applied to the location
-     * @param location Location to gain permissions
-     */
-    public JcloudsLocationSecurityGroupCustomizer addPermissionsToLocation(final JcloudsMachineLocation location, final Iterable<IpPermission> permissions) {
-        ComputeService computeService = location.getParent().getComputeService();
-        String nodeId = location.getNode().getId();
-        addPermissionsToLocation(permissions, nodeId, computeService);
-        return this;
-    }
-
-    /**
-     * Applies the given security group permissions to the given node with the given compute service.
-     * <p>
-     * Takes no action if the compute service does not have a security group extension.
-     * @param permissions The set of permissions to be applied to the node
-     * @param nodeId The id of the node to update
-     * @param computeService The compute service to use to apply the changes
-     */
-    @VisibleForTesting
-    void addPermissionsToLocation(Iterable<IpPermission> permissions, final String nodeId, ComputeService computeService) {
-        if (!computeService.getSecurityGroupExtension().isPresent()) {
-            LOG.warn("Security group extension for {} absent; cannot update node {} with {}",
-                    new Object[] {computeService, nodeId, permissions});
-            return;
-        }
-        final SecurityGroupExtension securityApi = computeService.getSecurityGroupExtension().get();
-        final String locationId = computeService.getContext().unwrap().getId();
-
-        // Expect to have two security groups on the node: one shared between all nodes in the location,
-        // that is cached in sharedGroupCache, and one created by Jclouds that is unique to the node.
-        // Relies on customize having been called before. This should be safe because the arguments
-        // needed to call this method are not available until post-instance creation.
-        SecurityGroup machineUniqueSecurityGroup;
-        Tasks.setBlockingDetails("Loading unique security group for node: " + nodeId);
-        try {
-            machineUniqueSecurityGroup = uniqueGroupCache.get(nodeId, new Callable<SecurityGroup>() {
-                @Override public SecurityGroup call() throws Exception {
-                    SecurityGroup sg = getUniqueSecurityGroupForNodeCachingSharedGroupIfPreviouslyUnknown(nodeId, locationId, securityApi);
-                    if (sg == null) {
-                        throw new IllegalStateException("Failed to find machine-unique group on node: " + nodeId);
-                    }
-                    return sg;
-                }
-            });
-        } catch (ExecutionException e) {
-            throw Throwables.propagate(new Exception(e.getCause()));
-        } finally {
-            Tasks.resetBlockingDetails();
-        }
-        for (IpPermission permission : permissions) {
-            addPermission(permission, machineUniqueSecurityGroup, securityApi);
-        }
-    }
-
-    /**
-     * Loads the security groups attached to the node with the given ID and returns the group
-     * that is unique to the node, per the application context. This method will also update
-     * {@link #sharedGroupCache} if no mapping for the shared group's location previously
-     * existed (e.g. Brooklyn was restarted and rebound to an existing application).
-     *
-     * Notice that jclouds will attach 2 securityGroups to the node if the locationId is `aws-ec2` so it needs to
-     * look for the uniqueSecurityGroup rather than the shared securityGroup.
-     *
-     * @param nodeId The id of the node in question
-     * @param locationId The id of the location in question
-     * @param securityApi The API to use to list security groups
-     * @return the security group unique to the given node, or null if one could not be determined.
-     */
-    private SecurityGroup getUniqueSecurityGroupForNodeCachingSharedGroupIfPreviouslyUnknown(String nodeId, String locationId, SecurityGroupExtension securityApi) {
-        Set<SecurityGroup> groupsOnNode = securityApi.listSecurityGroupsForNode(nodeId);
-        SecurityGroup unique;
-        if (locationId.equals("aws-ec2")) {
-            if (groupsOnNode.size() != 2) {
-                LOG.warn("Expected to find two security groups on node {} in app {} (one shared, one unique). Found {}: {}",
-                        new Object[]{nodeId, applicationId, groupsOnNode.size(), groupsOnNode});
-                return null;
-            }
-            String expectedSharedName = getNameForSharedSecurityGroup();
-            Iterator<SecurityGroup> it = groupsOnNode.iterator();
-            SecurityGroup shared = it.next();
-            if (shared.getName().endsWith(expectedSharedName)) {
-                unique = it.next();
-            } else {
-                unique = shared;
-                shared = it.next();
-            }
-            if (!shared.getName().endsWith(expectedSharedName)) {
-                LOG.warn("Couldn't determine which security group is shared between instances in app {}. Expected={}, found={}",
-                        new Object[]{applicationId, expectedSharedName, groupsOnNode});
-                return null;
-            }
-            // Shared entry might be missing if Brooklyn has rebound to an application
-            SecurityGroup old = sharedGroupCache.asMap().putIfAbsent(shared.getLocation(), shared);
-            LOG.info("Loaded unique security group for node {} (in {}): {}",
-                    new Object[]{nodeId, applicationId, unique});
-            if (old == null) {
-                LOG.info("Proactively set shared group for app {} to: {}", applicationId, shared);
-            }
-            return unique;
-        }
-        return Iterables.getOnlyElement(groupsOnNode);
-    }
-
-    /**
-     * Replaces security groups configured on the given template with one that allows
-     * SSH access on port 22 and allows communication on all ports between machines in
-     * the same group. Security groups are reused when templates have equal
-     * {@link org.jclouds.compute.domain.Template#getLocation locations}.
-     * <p>
-     * This method is called by Brooklyn when obtaining machines, as part of the
-     * {@link brooklyn.location.jclouds.JcloudsLocationCustomizer} contract. It
-     * should not be called from anywhere else.
-     *
-     * @param location The Brooklyn location that has called this method while obtaining a machine
-     * @param computeService The compute service being used by the location argument to provision a machine
-     * @param template The machine template created by the location argument
-     */
-    @Override
-    public void customize(JcloudsLocation location, ComputeService computeService, Template template) {
-        if (!computeService.getSecurityGroupExtension().isPresent()) {
-            LOG.warn("Security group extension for {} absent; cannot configure security groups in context: {}", computeService, applicationId);
-        } else if (template.getLocation() == null) {
-            LOG.warn("No location has been set on {}; cannot configure security groups in context: {}", template, applicationId);
-        } else {
-            LOG.info("Configuring security groups on location {} in context {}", location, applicationId);
-            setSecurityGroupOnTemplate(location, template, computeService.getSecurityGroupExtension().get());
-        }
-    }
-
-    private void setSecurityGroupOnTemplate(final JcloudsLocation location, final Template template, final SecurityGroupExtension securityApi) {
-        SecurityGroup shared;
-        Tasks.setBlockingDetails("Loading security group shared by instances in " + template.getLocation() +
-                " in app " + applicationId);
-        try {
-            shared = sharedGroupCache.get(template.getLocation(), new Callable<SecurityGroup>() {
-                @Override public SecurityGroup call() throws Exception {
-                    return getOrCreateSharedSecurityGroup(template.getLocation(), securityApi);
-                }
-            });
-        } catch (ExecutionException e) {
-            throw Throwables.propagate(new Exception(e.getCause()));
-        } finally {
-            Tasks.resetBlockingDetails();
-        }
-
-        Set<String> originalGroups = template.getOptions().getGroups();
-        template.getOptions().securityGroups(shared.getName());
-        if (!originalGroups.isEmpty()) {
-            LOG.info("Replaced configured security groups: configured={}, replaced with={}", originalGroups, template.getOptions().getGroups());
-        } else {
-            LOG.debug("Configured security groups at {} to: {}", location, template.getOptions().getGroups());
-        }
-    }
-
-    /**
-     * Loads the security group to be shared between nodes in the same application in the
-     * given Location. If no such security group exists it is created.
-     *
-     * @param location The location in which the security group will be found
-     * @param securityApi The API to use to list and create security groups
-     * @return the security group to share between instances in the given location in this application
-     */
-    private SecurityGroup getOrCreateSharedSecurityGroup(Location location, SecurityGroupExtension securityApi) {
-        final String groupName = getNameForSharedSecurityGroup();
-        // Could sort-and-search if straight search is too expensive
-        Optional<SecurityGroup> shared = Iterables.tryFind(securityApi.listSecurityGroupsInLocation(location), new Predicate<SecurityGroup>() {
-            @Override
-            public boolean apply(final SecurityGroup input) {
-                // endsWith because Jclouds prepends 'jclouds#' to security group names.
-                return input.getName().endsWith(groupName);
-            }
-        });
-        if (shared.isPresent()) {
-            LOG.info("Found existing shared security group in {} for app {}: {}",
-                    new Object[]{location, applicationId, groupName});
-            return shared.get();
-        } else {
-            LOG.info("Creating new shared security group in {} for app {}: {}",
-                    new Object[]{location, applicationId, groupName});
-            return createBaseSecurityGroupInLocation(groupName, location, securityApi);
-        }
-    }
-
-    /**
-     * Creates a security group with rules to:
-     * <ul>
-     *     <li>Allow SSH access on port 22 from the world</li>
-     *     <li>Allow TCP, UDP and ICMP communication between machines in the same group</li>
-     * </ul>
-     *
-     * It needs to consider locationId as port ranges and groupId are cloud provider-dependent e.g openstack nova
-     * wants from 1-65535 while aws-ec2 accepts from 0-65535.
-     *
-     *
-     * @param groupName The name of the security group to create
-     * @param location The location in which the security group will be created
-     * @param securityApi The API to use to create the security group
-     *
-     * @return the created security group
-     */
-    private SecurityGroup createBaseSecurityGroupInLocation(String groupName, Location location, SecurityGroupExtension securityApi) {
-        SecurityGroup group = addSecurityGroupInLocation(groupName, location, securityApi);
-
-        Set<String> openstackNovaIds = getJcloudsLocationIds("openstack-nova");
-
-        String groupId = group.getProviderId();
-        int fromPort = 0;
-        if (location.getParent() != null && Iterables.contains(openstackNovaIds, location.getParent().getId())) {
-            groupId = group.getId();
-            fromPort = 1;
-        }
-        // Note: For groupName to work with GCE we also need to tag the machines with the same ID.
-        // See sourceTags section at https://developers.google.com/compute/docs/networking#firewalls
-        IpPermission.Builder allWithinGroup = IpPermission.builder()
-                .groupId(groupId)
-                .fromPort(fromPort)
-                .toPort(65535);
-        addPermission(allWithinGroup.ipProtocol(IpProtocol.TCP).build(), group, securityApi);
-        addPermission(allWithinGroup.ipProtocol(IpProtocol.UDP).build(), group, securityApi);
-        addPermission(allWithinGroup.ipProtocol(IpProtocol.ICMP).fromPort(-1).toPort(-1).build(), group, securityApi);
-
-        IpPermission sshPermission = IpPermission.builder()
-                .fromPort(22)
-                .toPort(22)
-                .ipProtocol(IpProtocol.TCP)
-                .cidrBlock(getBrooklynCidrBlock())
-                .build();
-        addPermission(sshPermission, group, securityApi);
-
-        return group;
-    }
-
-    private Set<String> getJcloudsLocationIds(final String jcloudsApiId) {
-        Set<String> openstackNovaProviders = FluentIterable.from(Providers.all())
-                .filter(new Predicate<ProviderMetadata>() {
-            @Override
-            public boolean apply(ProviderMetadata providerMetadata) {
-                return providerMetadata.getApiMetadata().getId().equals(jcloudsApiId);
-            }
-        }).transform(new Function<ProviderMetadata, String>() {
-            @Nullable
-            @Override
-            public String apply(ProviderMetadata input) {
-                return input.getId();
-            }
-        }).toSet();
-
-        return new ImmutableSet.Builder<String>()
-                .addAll(openstackNovaProviders)
-                .add(jcloudsApiId)
-                .build();
-    }
-
-    protected SecurityGroup addSecurityGroupInLocation(final String groupName, final Location location, final SecurityGroupExtension securityApi) {
-        LOG.debug("Creating security group {} in {}", groupName, location);
-        Callable<SecurityGroup> callable = new Callable<SecurityGroup>() {
-            @Override
-            public SecurityGroup call() throws Exception {
-                return securityApi.createSecurityGroup(groupName, location);
-            }
-        };
-        return runOperationWithRetry(callable);
-    }
-
-    protected SecurityGroup addPermission(final IpPermission permission, final SecurityGroup group, final SecurityGroupExtension securityApi) {
-        LOG.debug("Adding permission to security group {}: {}", group.getName(), permission);
-        Callable<SecurityGroup> callable = new Callable<SecurityGroup>() {
-            @Override
-            public SecurityGroup call() throws Exception {
-                return securityApi.addIpPermission(permission, group);
-            }
-        };
-        return runOperationWithRetry(callable);
-    }
-
-    /** @return the CIDR block used to configure Brooklyn's in security groups */
-    public String getBrooklynCidrBlock() {
-        return sshCidrSupplier.get().toString();
-    }
-
-    /**
-     * @return The name to be used by security groups that will be shared between machines
-     *         in the same location for this instance's application context.
-     */
-    @VisibleForTesting
-    String getNameForSharedSecurityGroup() {
-        return "brooklyn-" + applicationId.toLowerCase() + "-shared";
-    }
-
-    /**
-     * Invalidates all entries in {@link #sharedGroupCache} and {@link #uniqueGroupCache}.
-     * Use to simulate the effects of rebinding Brooklyn to a deployment.
-     */
-    @VisibleForTesting
-    void clearSecurityGroupCaches() {
-        LOG.info("Clearing security group caches");
-        sharedGroupCache.invalidateAll();
-        uniqueGroupCache.invalidateAll();
-    }
-
-    /**
-     * Runs the given callable. Repeats until the operation succeeds or {@link #isExceptionRetryable} indicates
-     * that the request cannot be retried.
-     */
-    protected <T> T runOperationWithRetry(Callable<T> operation) {
-        int backoff = 64;
-        Exception lastException = null;
-        for (int retries = 0; retries < 100; retries++) {
-            try {
-                return operation.call();
-            } catch (Exception e) {
-                lastException = e;
-                if (isExceptionRetryable.apply(e)) {
-                    LOG.debug("Attempt #{} failed to add security group: {}", retries + 1, e.getMessage());
-                    try {
-                        Thread.sleep(backoff);
-                    } catch (InterruptedException e1) {
-                        throw Exceptions.propagate(e1);
-                    }
-                    backoff = backoff << 1;
-                } else {
-                    break;
-                }
-            }
-        }
-
-        throw new RuntimeException("Unable to add security group rule; repeated errors from provider", lastException);
-    }
-
-    /**
-     * @return
-     *      A predicate that is true if an exception contains an {@link org.jclouds.aws.AWSResponseException}
-     *      whose error code is either <code>InvalidGroup.InUse</code>, <code>DependencyViolation</code> or
-     *      <code>RequestLimitExceeded</code>.
-     */
-    public static Predicate<Exception> newAwsExceptionRetryPredicate() {
-        return new AwsExceptionRetryPredicate();
-    }
-
-    private static class AwsExceptionRetryPredicate implements Predicate<Exception> {
-        // Error reference: http://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html
-        private static final Set<String> AWS_ERRORS_TO_RETRY = ImmutableSet.of(
-                "InvalidGroup.InUse", "DependencyViolation", "RequestLimitExceeded");
-
-        @Override
-        public boolean apply(Exception input) {
-            @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
-            AWSResponseException exception = Exceptions.getFirstThrowableOfType(input, AWSResponseException.class);
-            if (exception != null) {
-                String code = exception.getError().getCode();
-                return AWS_ERRORS_TO_RETRY.contains(code);
-            }
-            return false;
-        }
-    }
-
-    /**
-     * A supplier of CIDRs that loads the external IP address of the localhost machine.
-     */
-    private static class LocalhostExternalIpCidrSupplier implements Supplier<Cidr> {
-
-        private volatile Cidr cidr;
-
-        @Override
-        public Cidr get() {
-            Cidr local = cidr;
-            if (local == null) {
-                synchronized (this) {
-                    local = cidr;
-                    if (local == null) {
-                        String externalIp = LocalhostExternalIpLoader.getLocalhostIpWithin(Duration.seconds(5));
-                        cidr = local = new Cidr(externalIp + "/32");
-                    }
-                }
-            }
-            return local;
-        }
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/JcloudsPortForwarderExtension.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/JcloudsPortForwarderExtension.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/JcloudsPortForwarderExtension.java
deleted file mode 100644
index adfdde3..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/JcloudsPortForwarderExtension.java
+++ /dev/null
@@ -1,45 +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 brooklyn.location.jclouds.networking;
-
-import org.jclouds.compute.domain.NodeMetadata;
-
-import brooklyn.location.access.BrooklynAccessUtils;
-import brooklyn.location.access.PortForwardManager;
-import brooklyn.util.net.Cidr;
-import brooklyn.util.net.Protocol;
-
-import com.google.common.base.Optional;
-import com.google.common.net.HostAndPort;
-
-public interface JcloudsPortForwarderExtension {
-
-    /**
-     * Opens port forwarding (e.g. DNAT or iptables port-forwarding) to reach the given given 
-     * target port on this node (from the given cidr).
-     * 
-     * This should also register the port with the {@link PortForwardManager}, via 
-     * {@code portForwardManager.associate(node.getId(), result, targetPort)} so that
-     * subsequent calls to {@link BrooklynAccessUtils#getBrooklynAccessibleAddress(brooklyn.entity.Entity, int)}
-     * will know about the mapped port.
-     */
-    public HostAndPort openPortForwarding(NodeMetadata node, int targetPort, Optional<Integer> optionalPublicPort, Protocol protocol, Cidr accessingCidr);
-
-    public void closePortForwarding(NodeMetadata node, int targetPort, HostAndPort publicHostAndPort, Protocol protocol);
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/SecurityGroupDefinition.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/SecurityGroupDefinition.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/SecurityGroupDefinition.java
deleted file mode 100644
index 7ced79f..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/SecurityGroupDefinition.java
+++ /dev/null
@@ -1,103 +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 brooklyn.location.jclouds.networking;
-
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import org.jclouds.aws.ec2.AWSEC2Api;
-import org.jclouds.compute.ComputeServiceContext;
-import org.jclouds.net.domain.IpPermission;
-import org.jclouds.net.domain.IpProtocol;
-import org.jclouds.net.util.IpPermissions;
-
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.net.Cidr;
-import brooklyn.util.text.Identifiers;
-
-import com.google.common.annotations.Beta;
-
-/** WIP to define a security group in an up-front way, where subsequently it can be applied to a jclouds location */
-@Beta
-public class SecurityGroupDefinition {
-
-    private Callable<String> groupNameFactory = new Callable<String>() { public String call() { return "br-sg-"+Identifiers.makeRandomId(8); } };
-    private List<IpPermission> ipPerms = MutableList.of();
-    
-    public void createGroupInAwsRegion(ComputeServiceContext computeServiceContext, String region) {
-        AWSEC2Api ec2Client = computeServiceContext.unwrapApi(AWSEC2Api.class);
-        String sgId = ec2Client.getSecurityGroupApi().get().createSecurityGroupInRegionAndReturnId(region, getName(), "Brooklyn-managed security group "+getName());
-        ec2Client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(region, sgId, ipPerms);
-    }
-
-    /** allows access to the given port on TCP from within the subnet */
-    public SecurityGroupDefinition allowingInternalPort(int port) {
-        return allowing(IpPermissions.permit(IpProtocol.TCP).port(port));
-    }
-    public SecurityGroupDefinition allowingInternalPorts(int port1, int port2, int ...ports) {
-        allowing(IpPermissions.permit(IpProtocol.TCP).port(port1));
-        allowing(IpPermissions.permit(IpProtocol.TCP).port(port2));
-        for (int port: ports)
-            allowing(IpPermissions.permit(IpProtocol.TCP).port(port));
-        return this;
-    }
-    public SecurityGroupDefinition allowingInternalPortRange(int portRangeStart, int portRangeEnd) {
-        return allowing(IpPermissions.permit(IpProtocol.TCP).fromPort(portRangeStart).to(portRangeEnd));
-    }
-    public SecurityGroupDefinition allowingInternalPing() {
-        return allowing(IpPermissions.permit(IpProtocol.ICMP));
-    }
-    
-    public SecurityGroupDefinition allowingPublicPort(int port) {
-        return allowing(IpPermissions.permit(IpProtocol.TCP).port(port).originatingFromCidrBlock(Cidr.UNIVERSAL.toString()));
-    }
-    public SecurityGroupDefinition allowingPublicPorts(int port1, int port2, int ...ports) {
-        allowing(IpPermissions.permit(IpProtocol.TCP).port(port1).originatingFromCidrBlock(Cidr.UNIVERSAL.toString()));
-        allowing(IpPermissions.permit(IpProtocol.TCP).port(port2).originatingFromCidrBlock(Cidr.UNIVERSAL.toString()));
-        for (int port: ports)
-            allowing(IpPermissions.permit(IpProtocol.TCP).port(port).originatingFromCidrBlock(Cidr.UNIVERSAL.toString()));
-        return this;
-    }
-    public SecurityGroupDefinition allowingPublicPortRange(int portRangeStart, int portRangeEnd) {
-        return allowing(IpPermissions.permit(IpProtocol.TCP).fromPort(portRangeStart).to(portRangeEnd).originatingFromCidrBlock(Cidr.UNIVERSAL.toString()));
-    }
-    public SecurityGroupDefinition allowingPublicPing() {
-        return allowing(IpPermissions.permit(IpProtocol.ICMP).originatingFromCidrBlock(Cidr.UNIVERSAL.toString()));
-    }
-    
-    public SecurityGroupDefinition allowing(IpPermission permission) {
-        ipPerms.add(permission);
-        return this;
-    }
-    
-    // TODO use cloud machine namer
-    public SecurityGroupDefinition named(final String name) {
-        groupNameFactory = new Callable<String>() { public String call() { return name; } };
-        return this;
-    }
-    public String getName() { 
-        try { return groupNameFactory.call(); } 
-        catch (Exception e) { throw Exceptions.propagate(e); } 
-    }
-
-    public Iterable<IpPermission> getPermissions() {
-        return ipPerms;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/SecurityGroupTool.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/SecurityGroupTool.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/SecurityGroupTool.java
deleted file mode 100644
index 31b06a0..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/networking/SecurityGroupTool.java
+++ /dev/null
@@ -1,167 +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 brooklyn.location.jclouds.networking;
-
-import java.util.Set;
-
-import org.jclouds.aws.ec2.AWSEC2Api;
-import org.jclouds.aws.util.AWSUtils;
-import org.jclouds.compute.domain.SecurityGroup;
-import org.jclouds.compute.extensions.SecurityGroupExtension;
-import org.jclouds.net.domain.IpPermission;
-import org.jclouds.rest.ApiContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.location.jclouds.JcloudsLocation;
-import brooklyn.location.jclouds.JcloudsLocationConfig;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.text.Strings;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-/** WIP to apply a security group to a jclouds endpoint.
- * <p>
- * sections of this code have been used but overall it is not yet in a working state,
- * but merged May 2014 to make it easier to pick up if and when needed.
- * (if not needed after several months this may simply be removed.) */
-@Beta
-public class SecurityGroupTool {
-
-    private static final Logger log = LoggerFactory.getLogger(SecurityGroupTool.class);
-    
-    protected final JcloudsLocation location;
-    protected final SecurityGroupDefinition sgDef;
-
-    public SecurityGroupTool(JcloudsLocation location, SecurityGroupDefinition sgDef) {
-        this.location = Preconditions.checkNotNull(location);
-        this.sgDef = Preconditions.checkNotNull(sgDef);
-    }
-    
-    public String getName() {
-        return sgDef.getName();
-    }
-    
-    public void apply() {
-        Optional<SecurityGroupExtension> sgExtO = location.getComputeService().getSecurityGroupExtension();
-        if (!sgExtO.isPresent()) {
-            throw new IllegalStateException("Advanced networking not supported in this location ("+location+")");
-        }
-        SecurityGroupExtension sgExt = sgExtO.get();
-        
-        SecurityGroup sg = findSecurityGroupWithName(sgExt, getName());
-        if (sg==null) {
-            // TODO initialize the location
-            org.jclouds.domain.Location sgLoc = null;
-
-            // TODO record that we created it
-            // create it
-            try {
-                // FIXME this will always fail for providers which need a location, until we set it above
-                // https://github.com/brooklyncentral/brooklyn/pull/1343#discussion_r12275188
-                sg = sgExt.createSecurityGroup(getName(), sgLoc);
-            } catch (Exception e) {
-                Exceptions.propagateIfFatal(e);
-                // check if someone else already created it
-                sg = findSecurityGroupWithName(sgExt, getName());
-                if (sg==null) {
-                    // no - so propagate error
-                    throw Exceptions.propagate(e);
-                } else {
-                    log.debug("Looks like parallel thread created security group "+getName()+"; ignoring error in our thread ("+e+") as we now have an SG");
-                }
-            }
-        }
-        
-        if (sg==null)
-            throw new IllegalStateException("Unable to find or create security group ID for "+getName());
-
-        addPermissions(sgExt, sg);
-    }
-    
-    protected SecurityGroup findSecurityGroupWithName(SecurityGroupExtension sgExt, String name) {
-        Set<SecurityGroup> groups = sgExt.listSecurityGroups();
-        // jclouds appends this sometimes so for portability let's add this
-        String nameAlt = name.startsWith("jclouds#") ? Strings.removeFromStart(name, "jclouds#") : "jclouds#"+name;
-        for (SecurityGroup g: groups) {
-            if (name.equals(g.getName())) return g;
-            if (nameAlt.equals(g.getName())) return g;
-        }
-        return null;
-    }
-
-    protected void addPermissions(SecurityGroupExtension sgExt, SecurityGroup sg) {
-
-        Object api = ((ApiContext<?>)location.getComputeService().getContext().unwrap()).getApi();
-        if (api instanceof AWSEC2Api) {
-            // optimization for AWS where rules can be added all at once, and it cuts down Req Limit Exceeded problems!
-            String region = AWSUtils.getRegionFromLocationOrNull(sg.getLocation());
-            String id = sg.getProviderId();
-            
-            ((AWSEC2Api)api).getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(region, id, sgDef.getPermissions());
-            
-        } else {
-            for (IpPermission p: sgDef.getPermissions()) {
-                sgExt.addIpPermission(p, sg);
-            }
-        }
-    }
-    
-    
-    // TODO remove this method once we've confirmed the above works nicely (this is an early attempt)
-    protected void applyOldEc2(AWSEC2Api client) {
-        String region = location.getConfig(JcloudsLocationConfig.CLOUD_REGION_ID);
-        if (region==null) {
-            // TODO where does the default come from?
-            log.warn("No region set for "+location+"; assuming EC2");
-            region = "us-east-1"; 
-        }
-        
-        Set<org.jclouds.ec2.domain.SecurityGroup> groups = client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(region, getName());
-        String id = null;
-        if (groups.isEmpty()) {
-            // create it
-            try {
-                id = client.getSecurityGroupApi().get().createSecurityGroupInRegionAndReturnId(region , getName(), "Brooklyn-managed security group "+getName());
-            } catch (Exception e) {
-                Exceptions.propagateIfFatal(e);
-                // check if someone else already created it!
-                groups = client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(region, getName());
-                if (groups.isEmpty()) {
-                    // no - so propagate error
-                    throw Exceptions.propagate(e);
-                } else {
-                    log.debug("Looks like parallel thread created security group "+getName()+"; ignoring error in our thread ("+e+") as we now have an SG");
-                }
-            }
-        }
-        if (!groups.isEmpty()) {
-            if (groups.size()>1)
-                log.warn("Multiple security groups matching '"+getName()+"' (using the first): "+groups);
-            id = groups.iterator().next().getId();
-        }
-        if (id==null)
-            throw new IllegalStateException("Unable to find or create security group ID for "+getName());
-
-        client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(region, id, sgDef.getPermissions());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachinePool.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachinePool.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachinePool.java
deleted file mode 100644
index d2dcf80..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachinePool.java
+++ /dev/null
@@ -1,395 +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 brooklyn.location.jclouds.pool;
-
-import static brooklyn.location.jclouds.pool.MachinePoolPredicates.compose;
-import static brooklyn.location.jclouds.pool.MachinePoolPredicates.matching;
-
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.domain.ComputeMetadata;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.Template;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
-/**
- * Contains details of machines detected at a given cloud (ComputeService),
- * and records claims made against those machines via this pool.
- * <p>
- * Machine instances themselves are persisted and rescanned as new instances of this class are created.
- * Claims however are specific to this instance of the class, i.e. <b>not</b> persisted.
- * <p>
- * This class is believed to be thread-safe.
- * Refreshes to the remote detected machines are synchronized on the pool instance.
- * Details of detected and claimed machines are also synchronized on the pool instance.
- * (If it is necessary to claim machines whilst the pool is being rescanned,
- * we can investigate a more sophisticated threading model.
- * Access to some fields is clearly independent and uses a tighter synchonization
- * strategy, e.g. templates.  
- * Synchronization of fields within a synch block on the class instance
- * is permitted, but not the other way round,
- * and synching on multiple fields is also not permitted.)
- * <p>
- * Callers wishing to guarantee results of e.g. ensureUnclaimed remaining available
- * can synchronize on this class for the duration that they wish to have that guarantee
- * (at the cost, of course, of any other threads being able to access this pool).
- * <p>
- * If underlying provisioning/destroying operations fail, the pool
- * currently may be in an unknown state, currently.
- * If more robustness is needed this can be added.
- * 
- * @deprecated since 0.6.0; never used in production setting, and thus of dubious value; best avoided as unlikely to be supported in future versions
- */
-@Deprecated
-public class MachinePool {
-    
-    private static final Logger log = LoggerFactory.getLogger(MachinePool.class);
-    
-    protected final ComputeService computeService;
-    final AtomicBoolean refreshNeeded = new AtomicBoolean(true);
-    final List<ReusableMachineTemplate> templates = new ArrayList<ReusableMachineTemplate>();
-    String poolName = null;
-    
-    /** all machines detected, less those in the black list */
-    volatile MachineSet detectedMachines = new MachineSet();
-    volatile MachineSet matchedMachines = new MachineSet();
-    volatile MachineSet claimedMachines = new MachineSet();
-    volatile MachineSet blacklistedMachines = new MachineSet();
-    
-    public MachinePool(ComputeService computeService) {
-        this.computeService = computeService;
-    }
-    
-    protected synchronized void init() {
-        if (!refreshNeeded.get()) return;
-        refresh();
-    }
-    
-    public void setPoolName(String poolName) {
-        if (poolName!=null)
-            log.warn("Changing pool name of "+this+" (from "+this.poolName+" to "+poolName+") is discouraged.");
-        this.poolName = poolName;
-    }
-    /** pool name is used as a group/label by jclouds, for convenience only; 
-     * it has no special properties for detecting matching instances
-     * (use explicit tags on the templates, for that). 
-     * defaults to name of pool class and user name.
-     * callers should set pool name before getting, if using a custom name. */
-    public synchronized String getPoolName() {
-        if (poolName==null)
-            poolName = getClass().getSimpleName()+"-"+System.getProperty("user.name");
-        return poolName;
-    }
-    
-    /** refreshes the pool of machines from the server (finding all instances matching the registered templates) */
-    public synchronized void refresh() {
-        refreshNeeded.set(false);
-        Set<? extends ComputeMetadata> computes = computeService.listNodes();
-        Set<NodeMetadata> nodes = new LinkedHashSet<NodeMetadata>();
-        for (ComputeMetadata c: computes) {
-            if (c instanceof NodeMetadata) {
-                nodes.add((NodeMetadata)c);
-            } else {
-                // TODO should we try to fetch more info?
-                log.warn("MachinePool "+this+" ignoring non-Node record for remote machine: "+c);
-            }
-        }
-
-        MachineSet allNewDetectedMachines = new MachineSet(nodes);
-        MachineSet newDetectedMachines = filterForAllowedMachines(allNewDetectedMachines);
-        MachineSet oldDetectedMachines = detectedMachines;
-        MachineSet newMatchedMachines = new MachineSet();
-        detectedMachines = newDetectedMachines;
-
-        MachineSet appearedMachinesIncludingBlacklist = allNewDetectedMachines.removed(oldDetectedMachines);
-        MachineSet appearedMachines = filterForAllowedMachines(appearedMachinesIncludingBlacklist);
-        if (appearedMachinesIncludingBlacklist.size()>appearedMachines.size())
-            if (log.isDebugEnabled()) log.debug("Pool "+this+", ignoring "+(appearedMachinesIncludingBlacklist.size()-appearedMachines.size())+" disallowed");
-        int matchedAppeared = 0;
-        for (NodeMetadata m: appearedMachines) {
-            if (m.getStatus() != NodeMetadata.Status.RUNNING) {
-                if (log.isDebugEnabled()) 
-                    log.debug("Pool "+this+", newly detected machine "+m+", not running ("+m.getStatus()+")");
-            } else {
-                Set<ReusableMachineTemplate> ts = getTemplatesMatchingInstance(m);
-                if (!ts.isEmpty()) {
-                    matchedAppeared++;
-                    newMatchedMachines = newMatchedMachines.added(new MachineSet(m));
-                    if (log.isDebugEnabled()) 
-                        log.debug("Pool "+this+", newly detected machine "+m+", matches pool templates "+ts);
-                } else {
-                    if (log.isDebugEnabled()) 
-                        log.debug("Pool "+this+", newly detected machine "+m+", does not match any pool templates");
-                }
-            }
-        }
-        if (matchedAppeared>0) {
-            log.info("Pool "+this+" discovered "+matchedAppeared+" matching machines (of "+appearedMachines.size()+" total new; "+newDetectedMachines.size()+" total including claimed and unmatched)");
-        } else {
-            if (log.isDebugEnabled()) 
-                log.debug("Pool "+this+" discovered "+matchedAppeared+" matching machines (of "+appearedMachines.size()+" total new; "+newDetectedMachines.size()+" total including claimed and unmatched)");
-        }
-        matchedMachines = newMatchedMachines;
-    }
-
-    protected MachineSet filterForAllowedMachines(MachineSet input) {
-        return input.removed(blacklistedMachines);
-    }
-
-    // TODO template registry and claiming from a template could be a separate responsibility
-    
-    protected ReusableMachineTemplate registerTemplate(ReusableMachineTemplate template) {
-        registerTemplates(template);
-        return template;
-    }
-    protected void registerTemplates(ReusableMachineTemplate ...templatesToReg) {
-        synchronized (templates) { 
-            for (ReusableMachineTemplate template: templatesToReg)
-                templates.add(template); 
-        }
-    }
-    
-    protected ReusableMachineTemplate newTemplate(String name) {
-        return registerTemplate(new ReusableMachineTemplate(name));
-    }
-
-    
-    public List<ReusableMachineTemplate> getTemplates() {
-        List<ReusableMachineTemplate> result;
-        synchronized (templates) { result = ImmutableList.copyOf(templates); }
-        return result;
-    }
-    
-    /** all machines matching any templates */
-    public MachineSet all() {
-        init();
-        return matchedMachines;
-    }
-
-    /** machines matching any templates which have not been claimed */
-    public MachineSet unclaimed() {
-        init();
-        synchronized (this) {
-            return matchedMachines.removed(claimedMachines);
-        }
-    }
-    
-    /** returns all machines matching the given criteria (may be claimed) */
-    @SuppressWarnings("unchecked")
-    public MachineSet all(Predicate<NodeMetadata> criterion) {
-        // To avoid generics complaints in callers caused by varargs, overload here
-        return all(new Predicate[] {criterion});
-    }
-    
-    /** returns all machines matching the given criteria (may be claimed) */
-    public MachineSet all(Predicate<NodeMetadata> ...ops) {
-        return new MachineSet(Iterables.filter(all(), compose(ops)));
-    }
-
-    /** returns unclaimed machines matching the given criteria */
-    @SuppressWarnings("unchecked")
-    public MachineSet unclaimed(Predicate<NodeMetadata> criterion) {
-        // To avoid generics complaints in callers caused by varargs, overload here
-        return unclaimed(new Predicate[] {criterion});
-    }
-    
-    /** returns unclaimed machines matching the given criteria */
-    public MachineSet unclaimed(Predicate<NodeMetadata> ...criteria) {
-        return new MachineSet(Iterables.filter(unclaimed(), compose(criteria)));
-    }
-
-    /** creates machines if necessary so that this spec exists (may already be claimed however) 
-     * returns a set of all matching machines, guaranteed non-empty 
-     * (but possibly some are already claimed) */
-    public MachineSet ensureExists(ReusableMachineTemplate template) {
-        return ensureExists(1, template);
-    }
-
-    public synchronized void addToBlacklist(MachineSet newToBlacklist) {
-        setBlacklist(blacklistedMachines.added(newToBlacklist));
-    }
-    
-    /** replaces the blacklist set; callers should generally perform a refresh()
-     * afterwards, to trigger re-detection of blacklisted machines
-     */
-    public synchronized void setBlacklist(MachineSet newBlacklist) {
-        blacklistedMachines = newBlacklist;
-        detectedMachines = detectedMachines.removed(blacklistedMachines);
-        matchedMachines = matchedMachines.removed(blacklistedMachines);
-    }
-    
-    /** creates machines if necessary so that this spec exists (may already be claimed however);
-     * returns a set of all matching machines, of size at least count (but possibly some are already claimed).
-     * (the pool can change at any point, so this set is a best-effort but may be out of date.
-     * see javadoc comments on this class.) */
-    public MachineSet ensureExists(int count, ReusableMachineTemplate template) {
-        MachineSet current;
-        current = all(matching(template));
-        if (current.size() >= count)
-            return current;
-        //have to create more
-        MachineSet moreNeeded = create(count-current.size(), template);
-        return current.added(moreNeeded);
-    }
-    
-    /** creates machines if necessary so that this spec can subsequently be claimed;
-     * returns all such unclaimed machines, guaranteed to be non-empty.
-    * (the pool can change at any point, so this set is a best-effort but may be out of date.
-    * see javadoc comments on this class.) */
-    public MachineSet ensureUnclaimed(ReusableMachineTemplate template) {
-        return ensureUnclaimed(1, template);
-    }
-
-    /** creates machines if necessary so that this spec can subsequently be claimed;
-     * returns a set of at least count unclaimed machines */
-    public MachineSet ensureUnclaimed(int count, ReusableMachineTemplate template) {
-        MachineSet current;
-        current = unclaimed(matching(template));
-        if (current.size() >= count)
-            return current;
-        //have to create more
-        MachineSet moreNeeded = create(count-current.size(), template);
-        return current.added(moreNeeded);
-    }
-
-    public Set<ReusableMachineTemplate> getTemplatesMatchingInstance(NodeMetadata nm) {
-        Set<ReusableMachineTemplate> result = new LinkedHashSet<ReusableMachineTemplate>(); 
-        for (ReusableMachineTemplate t: getTemplates()) {
-            if (matching(t).apply(nm)) {
-               result.add(t); 
-            }
-        }        
-        return result;
-    }
-    
-    /** creates the given number of machines of the indicated template */
-    public MachineSet create(int count, ReusableMachineTemplate template) {
-        Set<? extends NodeMetadata> nodes;
-        try {
-            Template t = template.newJcloudsTemplate(computeService);
-            if (log.isDebugEnabled()) log.debug("Creating "+count+" new instances of "+t);
-            nodes = computeService.createNodesInGroup(getPoolName(), count, t);
-        } catch (RunNodesException e) {
-            throw Throwables.propagate(e);
-        }
-        MachineSet result = new MachineSet(nodes);
-        registerNewNodes(result, template);
-        return result;
-    }
-    protected void registerNewNodes(MachineSet result, ReusableMachineTemplate template) {
-        for (NodeMetadata m: result) {
-            Set<ReusableMachineTemplate> ts = getTemplatesMatchingInstance(m);
-            if (ts.isEmpty()) {
-                log.error("Pool "+this+", created machine "+m+" from template "+template+", but no pool templates match!");
-            } else {
-                if (log.isDebugEnabled())
-                    log.debug("Pool "+this+", created machine "+m+" from template "+template+", matching templates "+ts);
-            }
-        }
-        synchronized (this) {
-            detectedMachines = detectedMachines.added(result);
-            matchedMachines = matchedMachines.added(result);
-        }
-    }
-
-    /** claims the indicated number of machines with the indicated spec, creating if necessary */
-    public MachineSet claim(int count, ReusableMachineTemplate t) {
-        init();
-        Set<NodeMetadata> claiming = new LinkedHashSet<NodeMetadata>();
-        while (claiming.size() < count) {
-            MachineSet mm = ensureUnclaimed(count - claiming.size(), t);
-            for (NodeMetadata m : mm) {
-                synchronized (this) {
-                    if (claiming.size() < count && !claimedMachines.contains(m)) {
-                        claiming.add(m);
-                        claimedMachines = claimedMachines.added(new MachineSet(m));
-                    }
-                }
-            }
-        }
-        MachineSet result = new MachineSet(claiming);
-        return result;
-    }
-
-
-    /** claims the indicated set of machines;
-     * throws exception if cannot all be claimed;
-     * returns the set passed in if successful */
-    public MachineSet claim(MachineSet set) {
-        init();
-        synchronized (this) {
-            MachineSet originalClaimed = claimedMachines;
-            claimedMachines = claimedMachines.added(set);
-            MachineSet newlyClaimed = claimedMachines.removed(originalClaimed);
-            if (newlyClaimed.size() != set.size()) {
-                //did not claim all; unclaim and fail
-                claimedMachines = originalClaimed;
-                MachineSet unavailable = set.removed(newlyClaimed); 
-                throw new IllegalArgumentException("Could not claim all requested machines; failed to claim "+unavailable);
-            }
-            return newlyClaimed;
-        }
-    }
-    
-    public int unclaim(MachineSet set) {
-        init();
-        synchronized (this) {
-            MachineSet originalClaimed = claimedMachines;
-            claimedMachines = claimedMachines.removed(set);
-            return originalClaimed.size() - claimedMachines.size();
-        }
-    }
-
-    
-    public int destroy(final MachineSet set) {
-        init();
-        synchronized (this) {
-            detectedMachines = detectedMachines.removed(set);
-            matchedMachines = matchedMachines.removed(set);
-            claimedMachines = claimedMachines.removed(set);
-        }
-        Set<? extends NodeMetadata> destroyed = computeService.destroyNodesMatching(new Predicate<NodeMetadata>() {
-            @Override
-            public boolean apply(NodeMetadata input) {
-                return set.contains(input);
-            }
-        });
-        synchronized (this) {
-            //in case a rescan happened while we were destroying
-            detectedMachines = detectedMachines.removed(set);
-            matchedMachines = matchedMachines.removed(set);
-            claimedMachines = claimedMachines.removed(set);
-        }
-        return destroyed.size();        
-    }
-        
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachinePoolPredicates.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachinePoolPredicates.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachinePoolPredicates.java
deleted file mode 100644
index e2158c1..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachinePoolPredicates.java
+++ /dev/null
@@ -1,149 +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 brooklyn.location.jclouds.pool;
-
-import java.util.Map;
-
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.Processor;
-import org.jclouds.domain.Location;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Throwables;
-
-public class MachinePoolPredicates {
-
-    private static final Logger log = LoggerFactory.getLogger(MachinePoolPredicates.class);
-    
-    public static Predicate<NodeMetadata> except(final MachineSet removedItems) {
-        return new Predicate<NodeMetadata>() {
-            @Override
-            public boolean apply(NodeMetadata input) {
-                return !removedItems.contains(input);
-            }
-        };
-    }
-
-    public static Predicate<NodeMetadata> except(final Predicate<NodeMetadata> predicateToExclude) {
-        return Predicates.not(predicateToExclude);
-    }
-
-    public static Predicate<NodeMetadata> matching(final ReusableMachineTemplate template) {
-        return new Predicate<NodeMetadata>() {
-            @Override
-            public boolean apply(NodeMetadata input) {
-                return matches(template, input);
-            }
-        };
-    }
-
-    public static Predicate<NodeMetadata> withTag(final String tag) {
-        return new Predicate<NodeMetadata>() {
-            @Override
-            public boolean apply(NodeMetadata input) {
-                return input.getTags().contains(tag);
-            }
-        };
-    }
-
-    public static Predicate<NodeMetadata> compose(final Predicate<NodeMetadata> ...predicates) {
-        return Predicates.and(predicates);
-    }
-
-    /** True iff the node matches the criteria specified in this template. 
-     * <p>
-     * NB: This only checks some of the most common fields, 
-     * plus a hashcode (in strict mode).  
-     * In strict mode you're practically guaranteed to match only machines created by this template.
-     * (Add a tag(uid) and you _will_ be guaranteed, strict mode or not.)
-     * <p> 
-     * Outside strict mode, some things (OS and hypervisor) can fall through the gaps.  
-     * But if that is a problem we can easily add them in.
-     * <p>
-     * (Caveat: If explicit Hardware, Image, and/or Template were specified in the template,
-     * then the hash code probably will not detect it.)   
-     **/
-    public static boolean matches(ReusableMachineTemplate template, NodeMetadata m) {
-        try {
-            // tags and user metadata
-
-            if (! m.getTags().containsAll( template.getTags(false) )) return false;
-
-            if (! isSubMapOf(template.getUserMetadata(false), m.getUserMetadata())) return false;
-
-
-            // common hardware parameters
-
-            if (template.getMinRam()!=null && m.getHardware().getRam() < template.getMinRam()) return false;
-
-            if (template.getMinCores()!=null) {
-                double numCores = 0;
-                for (Processor p: m.getHardware().getProcessors()) numCores += p.getCores();
-                if (numCores+0.001 < template.getMinCores()) return false;
-            }
-
-            if (template.getIs64bit()!=null) {
-                if (m.getOperatingSystem().is64Bit() != template.getIs64bit()) return false;
-            }
-
-            if (template.getOsFamily()!=null) {
-                if (m.getOperatingSystem() == null || 
-                        !template.getOsFamily().equals(m.getOperatingSystem().getFamily())) return false;
-            }
-            if (template.getOsNameMatchesRegex()!=null) {
-                if (m.getOperatingSystem() == null || m.getOperatingSystem().getName()==null ||
-                        !m.getOperatingSystem().getName().matches(template.getOsNameMatchesRegex())) return false;
-            }
-
-            if (template.getLocationId()!=null) {
-                if (!isLocationContainedIn(m.getLocation(), template.getLocationId())) return false;
-            }
-
-            // TODO other TemplateBuilder fields and TemplateOptions
-
-            return true;
-            
-        } catch (Exception e) {
-            log.warn("Error (rethrowing) trying to match "+m+" against "+template+": "+e, e);
-            throw Throwables.propagate(e);
-        }
-    }
-
-    private static boolean isLocationContainedIn(Location location, String locationId) {
-        if (location==null) return false;
-        if (locationId.equals(location.getId())) return true;
-        return isLocationContainedIn(location.getParent(), locationId);
-    }
-
-    public static boolean isSubMapOf(Map<String, String> sub, Map<String, String> bigger) {
-        for (Map.Entry<String, String> e: sub.entrySet()) {
-            if (e.getValue()==null) {
-                if (!bigger.containsKey(e.getKey())) return false;
-                if (bigger.get(e.getKey())!=null) return false;
-            } else {
-                if (!e.getValue().equals(bigger.get(e.getKey()))) return false;
-            }
-        }
-        return true;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachineSet.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachineSet.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachineSet.java
deleted file mode 100644
index fe21e2a..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/MachineSet.java
+++ /dev/null
@@ -1,98 +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 brooklyn.location.jclouds.pool;
-
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import javax.annotation.concurrent.Immutable;
-
-import org.jclouds.compute.domain.NodeMetadata;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-@Immutable
-public class MachineSet implements Iterable<NodeMetadata> {
-
-    final Set<NodeMetadata> members;
-    
-    public MachineSet(Iterable<? extends NodeMetadata> m) { 
-        members = ImmutableSet.copyOf(m); 
-    }
-    public MachineSet(NodeMetadata ...nodes) {
-        members = ImmutableSet.copyOf(nodes); 
-    }
-
-    @Override
-    public Iterator<NodeMetadata> iterator() {
-        return members.iterator();
-    }
-
-    public MachineSet removed(MachineSet toRemove) {
-        Set<NodeMetadata> s = new LinkedHashSet<NodeMetadata>(members);
-        for (NodeMetadata m: toRemove) s.remove(m);
-        return new MachineSet(s);
-    }
-    public MachineSet added(MachineSet toAdd) {
-        Set<NodeMetadata> s = new LinkedHashSet<NodeMetadata>(members);
-        for (NodeMetadata m: toAdd) s.add(m);
-        return new MachineSet(s);
-    }
-
-    @SuppressWarnings("unchecked")
-    public MachineSet filtered(Predicate<NodeMetadata> criterion) {
-        // To avoid generics complaints in callers caused by varargs, overload here
-        return filtered(new Predicate[] {criterion});
-    }
-
-    public MachineSet filtered(Predicate<NodeMetadata> ...criteria) {
-        return new MachineSet(Iterables.filter(members, MachinePoolPredicates.compose(criteria)));
-    }
-
-    public int size() {
-        return members.size();
-    }
-    
-    public boolean isEmpty() {
-        return members.isEmpty();
-    }
-    
-    public boolean contains(NodeMetadata input) {
-        return members.contains(input);
-    }
-    
-    @Override
-    public String toString() {
-        return members.toString();
-    }
-    
-    @Override
-    public int hashCode() {
-        return members.hashCode();
-    }
-    
-    @Override
-    public boolean equals(Object obj) {
-        return (obj instanceof MachineSet) && (members.equals( ((MachineSet)obj).members ));
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java
deleted file mode 100644
index d1f3331..0000000
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java
+++ /dev/null
@@ -1,183 +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 brooklyn.location.jclouds.pool;
-
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.jclouds.compute.options.TemplateOptions;
-
-import brooklyn.location.jclouds.templates.PortableTemplateBuilder;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
-/**
- * A facility for having a template we can declare without knowing the provider,
- * then find matching instances, create instances, and generally manipulate them.
- * <p>
- * NB: to be sure of matching a specific template, you should provide a unique id in the constructor.
- * (this will force 'strict' mode.)
- */
-// TODO tags/metadata semantics are not quite right, as they could apply to the server _image_ or _instance_
-
-// TODO we could use a hashcode over the values of template-builder and template-options fields, as a tag/usermetadata, 
-// to guarantee (virtually) matching only machines created from this template (instead of asking for unique id)
-public class ReusableMachineTemplate extends PortableTemplateBuilder<ReusableMachineTemplate> {
-
-    public static final String PREFIX = "brooklyn:template.";
-    public static final String NAME_METADATA_KEY = PREFIX+"name";
-    public static final String DESCRIPTION_METADATA_KEY = PREFIX+"name";
-    public static final String HASH_METADATA_KEY = PREFIX+"hash";
-    public static final String TEMPLATE_OWNER_METADATA_KEY = PREFIX+"owner";
-    
-    private String name = null;
-    private String templateOwner = null;
-    private String description = null;
-    private boolean strict;
-    
-    public ReusableMachineTemplate() { strict = false; }
-    public ReusableMachineTemplate(String name) { name(name); }
-    
-    /** see #getName() */
-    public ReusableMachineTemplate name(String name) {
-        this.name = name;
-        strict = true;
-        return this;
-    }
-    
-    /** see #getDescription() */
-    public ReusableMachineTemplate description(String description) {
-        this.description = description;
-        return this;
-    }
-
-    /** whether this template only matches machines instances created from this template; 
-     * defaults true if a name is set, otherwise false.
-     * if false, it will ignore name, owner, and hashcode */
-    public ReusableMachineTemplate strict(boolean strict) {
-        this.strict = strict;
-        return this;
-    }
-
-    /** no owner, means anyone can pick this up (default) */
-    public ReusableMachineTemplate templateUnowned() {
-        return templateOwner(null);
-    }
-    /** adds user.name as owner of this template */
-    public ReusableMachineTemplate templateOwnedByMe() {
-        return templateOwner(System.getProperty("user.name"));
-    }
-    /** adds an owner tag to this template */
-    public ReusableMachineTemplate templateOwner(String owner) {
-        this.templateOwner = owner;
-        return this;
-    }
-    
-    /** human-friendly name for this template. should normally be unique, it is the primary differentiator for strict matching. */
-    public String getName() {
-        return name;
-    }
-    
-    /** a description for this template; this is set on created machines but _not_ used to filter them 
-     * (so you can change description freely).  */
-    public String getDescription() {
-        return description;
-    }
-    
-    public String getOwner() {
-        return templateOwner;
-    }
-    
-    public boolean isStrict() {
-        return strict;
-    }
-
-    @Override
-    public List<TemplateOptions> getAdditionalOptions() {
-        List<TemplateOptions> result = new ArrayList<TemplateOptions>();
-        result.addAll(super.getAdditionalOptions());
-        if (isStrict()) addStrictOptions(result);
-        return result;
-    }
-
-    @Override
-    public List<TemplateOptions> getAdditionalOptionalOptions() {
-        List<TemplateOptions> result = new ArrayList<TemplateOptions>();
-        result.addAll(super.getAdditionalOptions());
-        addStrictOptions(result);
-        return result;
-    }
-    
-    protected void addStrictOptions(List<TemplateOptions> result) {
-        if (name!=null) result.add(TemplateOptions.Builder.userMetadata(NAME_METADATA_KEY, name));
-        if (templateOwner!=null) result.add(TemplateOptions.Builder.userMetadata(TEMPLATE_OWNER_METADATA_KEY, templateOwner));
-        // this is too strict -- the hash code seems to change from run to run (would be nice to fix that)
-//        result.add(TemplateOptions.Builder.userMetadata(HASH_METADATA_KEY, ""+hashCode()));
-    }
-    
-    /** computes the user metadata that this template will set (argument true) or required to match (argument false) */
-    public Map<String,String> getUserMetadata(boolean includeOptional) {
-        return ImmutableMap.copyOf(computeAggregatedOptions(includeOptional).getUserMetadata());
-    }
-
-    /** computes the tags that this template will set (argument true) or require to match (argument false) */
-    public Set<String> getTags(boolean includeOptional) {
-        return ImmutableSet.copyOf(computeAggregatedOptions(includeOptional).getTags());
-    }
-    
-    public ReusableMachineTemplate tag(String tag) {
-        return tags(tag);
-    }
-    public ReusableMachineTemplate tags(String ...tags) {
-        return addOptions(TemplateOptions.Builder.tags(Arrays.asList(tags)));
-    }
-
-    public ReusableMachineTemplate metadata(String key, String value) {
-        return addOptions(TemplateOptions.Builder.userMetadata(key, value));
-    }
-    public ReusableMachineTemplate metadata(Map<String,String> m) {
-        return addOptions(TemplateOptions.Builder.userMetadata(m));
-    }
-
-    public ReusableMachineTemplate tagOptional(String tag) {
-        return tagsOptional(tag);
-    }
-    public ReusableMachineTemplate tagsOptional(String ...tags) {
-        return addOptionalOptions(TemplateOptions.Builder.tags(Arrays.asList(tags)));
-    }
-
-    public ReusableMachineTemplate metadataOptional(String key, String value) {
-        return addOptionalOptions(TemplateOptions.Builder.userMetadata(key, value));
-    }
-    public ReusableMachineTemplate metadataOptional(Map<String,String> m) {
-        return addOptionalOptions(TemplateOptions.Builder.userMetadata(m));
-    }
-
-    @Override
-    public String toString() {
-        String s = makeNonTrivialArgumentsString();
-        return (name!=null ? name : "Template") + " [ " + s + " ]";
-    }
-    
-}