http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java
 
b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java
new file mode 100644
index 0000000..ea93685
--- /dev/null
+++ 
b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/pool/ReusableMachineTemplate.java
@@ -0,0 +1,182 @@
+/*
+ * 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.jclouds.pool;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.location.jclouds.templates.PortableTemplateBuilder;
+import org.jclouds.compute.options.TemplateOptions;
+
+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 + " ]";
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/AbstractPortableTemplateBuilder.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/AbstractPortableTemplateBuilder.java
 
b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/AbstractPortableTemplateBuilder.java
new file mode 100644
index 0000000..b73e7ec
--- /dev/null
+++ 
b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/AbstractPortableTemplateBuilder.java
@@ -0,0 +1,527 @@
+/*
+ * 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.jclouds.templates;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.options.TemplateOptions;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+
+public abstract class AbstractPortableTemplateBuilder<T extends 
AbstractPortableTemplateBuilder<?>> implements TemplateBuilder {
+
+    /** list of commands supplied by user, excluding options */
+    protected List<Function<TemplateBuilder,TemplateBuilder>> commands = new 
ArrayList<Function<TemplateBuilder,TemplateBuilder>>();
+    
+    private Hardware hardware;
+    private Image image;
+    private Template template;
+    private String locationId;
+    private String imageId;
+    private String hardwareId;
+    private OsFamily os;
+    private String osNameRegex;
+    private String osDescriptionRegex;
+    private String osVersionRegex;
+    private String osArchitectureRegex;
+    private String hypervisorRegex;
+    private Boolean is64bit;
+    private String imageNameRegex;
+    private String imageDescriptionRegex;
+    private String imageVersionRegex;
+    private Double minCores;
+    private Integer minRam;
+    private Double minDisk;
+    private Predicate<Image> imageCondition;
+    private Function<Iterable<? extends Image>, Image> imageChooserFunction;
+    /** this is the last options instance set by a call to 
options(TemplateOptions) */
+    private TemplateOptions options;
+    /** these are extra options that we want _added_, in order, on top of the 
last options set */
+    private List<TemplateOptions> additionalOptions = new 
ArrayList<TemplateOptions>();
+    
+    @Override
+    public T any() {
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return b.any(); 
}});
+        return (T)this;
+    }
+
+    @Override
+    public T fromHardware(final Hardware hardware) {
+        this.hardware = hardware;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.fromHardware(hardware); }});
+        return (T)this;
+    }
+
+    public Hardware getHardware() {
+        return hardware;
+    }
+
+    @Override
+    public T fromImage(final Image image) {
+        this.image = image;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.fromImage(image); }});
+        return (T)this;
+    }
+    
+    public Image getImage() {
+        return image;
+    }
+
+    @Override
+    public T fromTemplate(final Template template) {
+        this.template = template;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.fromTemplate(template); }});
+        return (T)this;
+    }
+    
+    public Template getTemplate() {
+        return template;
+    }
+
+    @Override
+    public T smallest() {
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.smallest(); }});
+        return (T)this;
+    }
+
+    @Override
+    public T fastest() {
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.fastest(); }});
+        return (T)this;
+    }
+
+    @Override
+    public T biggest() {
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.biggest(); }});
+        return (T)this;
+    }
+
+    @Override
+    public T locationId(final String locationId) {
+        this.locationId = locationId;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.locationId(locationId); }});
+        return (T)this;
+    }
+    
+    public String getLocationId() {
+        return locationId;
+    }
+
+    @Override
+    public T imageId(final String imageId) {
+        this.imageId = imageId;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.imageId(imageId); }});
+        return (T)this;
+    }
+    
+    public String getImageId() {
+        return imageId;
+    }
+
+    @Override
+    public T hardwareId(final String hardwareId) {
+        this.hardwareId = hardwareId;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.hardwareId(hardwareId); }});
+        return (T)this;
+    }
+    
+    public String getHardwareId() {
+        return hardwareId;
+    }
+
+    @Override
+    public T osNameMatches(final String osNameRegex) {
+        this.osNameRegex = osNameRegex;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.osNameMatches(osNameRegex); }});
+        return (T)this;
+    }
+    
+    public String getOsNameMatchesRegex() {
+        return osNameRegex;
+    }
+
+    @Override
+    public T osDescriptionMatches(final String osDescriptionRegex) {
+        this.osDescriptionRegex = osDescriptionRegex;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.osDescriptionMatches(osDescriptionRegex); }});
+        return (T)this;
+    }
+    
+    public String getOsDescriptionMatchesRegex() {
+        return osDescriptionRegex;
+    }
+
+    @Override
+    public T osVersionMatches(final String osVersionRegex) {
+        this.osVersionRegex = osVersionRegex;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.osVersionMatches(osVersionRegex); }});
+        return (T)this;
+    }
+    
+    public String getOsVersionMatchesRegex() {
+        return osVersionRegex;
+    }
+
+    @Override
+    public T osArchMatches(final String osArchitectureRegex) {
+        this.osArchitectureRegex = osArchitectureRegex;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.osArchMatches(osArchitectureRegex); }});
+        return (T)this;
+    }
+    
+    public String getOsArchitectureMatchesRegex() {
+        return osArchitectureRegex;
+    }
+
+    @Override
+    public T os64Bit(final boolean is64bit) {
+        this.is64bit = is64bit;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.os64Bit(is64bit); }});
+        return (T)this;
+    }
+    
+    public Boolean getIs64bit() {
+        return is64bit;
+    }
+
+    @Override
+    public T osFamily(final OsFamily os) {
+        this.os = os;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.osFamily(os); }});
+        return (T)this;
+    }
+    
+    public OsFamily getOsFamily() {
+        return os;
+    }
+
+    @Override
+    public T hypervisorMatches(final String hypervisorRegex) {
+        this.hypervisorRegex = hypervisorRegex;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.hypervisorMatches(hypervisorRegex); }});
+        return (T)this;
+    }
+    
+    public String getHypervisorMatchesRegex() {
+        return hypervisorRegex;
+    }
+
+    @Override
+    public T imageNameMatches(final String imageNameRegex) {
+        this.imageNameRegex = imageNameRegex;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.imageNameMatches(imageNameRegex); }});
+        return (T)this;
+    }
+    
+    public String getImageNameMatchesRegex() {
+        return imageNameRegex;
+    }
+
+    @Override
+    public T imageDescriptionMatches(final String imageDescriptionRegex) {
+        this.imageDescriptionRegex = imageDescriptionRegex;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.imageDescriptionMatches(imageDescriptionRegex); }});
+        return (T)this;
+    }
+    
+    public String getImageDescriptionMatchesRegex() {
+        return imageDescriptionRegex;
+    }
+
+    @Override
+    public T imageVersionMatches(final String imageVersionRegex) {
+        this.imageVersionRegex = imageVersionRegex;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.imageVersionMatches(imageVersionRegex); }});
+        return (T)this;
+    }
+    
+    public String getImageVersionMatchesRegex() {
+        return imageVersionRegex;
+    }
+    
+    @Override
+    public T imageMatches(final Predicate<Image> condition) {
+        this.imageCondition = condition;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.imageMatches(condition); }});
+        return (T)this;
+    }
+    
+    public Predicate<Image> getImageMatchesCondition() {
+        return imageCondition;
+    }
+
+    @Override
+    public T minCores(final double minCores) {
+        this.minCores = minCores;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.minCores(minCores); }});
+        return (T)this;
+    }
+    
+    public Double getMinCores() {
+        return minCores;
+    }
+
+    @Override
+    public T minRam(final int megabytes) {
+        this.minRam = megabytes;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.minRam(megabytes); }});
+        return (T)this;
+    }
+    
+    /** megabytes */
+    public Integer getMinRam() {
+        return minRam;
+    }
+    
+    @Override
+    public T minDisk(final double gigabytes) {
+        this.minDisk = gigabytes;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.minDisk(gigabytes); }});
+        return (T)this;
+    }
+
+    /** megabytes */
+    public Double getMinDisk() {
+        return minDisk;
+    }
+
+    public T imageChooser(final Function<Iterable<? extends Image>, Image> 
imageChooserFunction) {
+        this.imageChooserFunction = imageChooserFunction;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.imageChooser(imageChooserFunction); }});
+        return (T)this;
+    }
+    
+    public Function<Iterable<? extends Image>, Image> imageChooser() {
+        return imageChooserFunction;
+    }
+
+    /** clears everything set in this template, including any default from the 
compute service */
+    // not sure this is that useful, as the default is only applied if there 
are no changes
+    public T blank() {
+        hardware = null;
+        image = null;
+        template = null;
+        hypervisorRegex = null;
+        os = null;
+        locationId = null;
+        imageId = null;
+        hardwareId = null;
+        osNameRegex = null;
+        osDescriptionRegex = null;
+        osVersionRegex = null;
+        osArchitectureRegex = null;
+        is64bit = null;
+        imageNameRegex = null;
+        imageDescriptionRegex = null;
+        imageVersionRegex = null;
+        imageCondition = null;
+        minCores = null;
+        minRam = null;
+        options = null;
+        additionalOptions.clear();
+
+        // clear all fields, and commands
+        commands.clear();
+        // then add a command to clear osName + Version + 64bit
+        osFamily(null);
+        osVersionMatches(null);
+        // no way to turn off 64-bitness, but it won't usually be turned on
+//        os64bit(null);
+        // set _something_ to prevent the default from applying
+        minRam(1);
+
+        return (T)this;
+    }
+    
+    /** true if the templateBuilder spec is blank (ignoring customization 
options e.g. tags for the resulting instance) */
+    public boolean isBlank() {
+        if (commands.isEmpty()) return true;
+        //also "blank" if we've blanked it
+        if (commands.size()==1 && (minRam!=null && minRam==1)) return true;
+        return false;
+    }
+    
+    @Override
+    public T options(final TemplateOptions options) {
+        this.options = options;
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.options(options); }});
+        return (T)this;
+    }
+
+    /** sets customization options; may be null if not set. use addOptions(new 
TemplateOptions()) to set new ones. */
+    public TemplateOptions getOptions() {
+        return options;
+    }
+    
+    /** adds customization options; if options have already been set, this 
will additively set selected options
+     * (but not all, see addTemplateOptions for more info)
+     */
+    public T addOptions(final TemplateOptions options) {
+        this.additionalOptions.add(options);
+        commands.add(new Function<TemplateBuilder,TemplateBuilder>() { 
+            public TemplateBuilder apply(TemplateBuilder b) { return 
b.options(options); }});
+        return (T)this;
+    }
+
+    public List<TemplateOptions> getAdditionalOptions() {
+        return ImmutableList.copyOf(additionalOptions);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(
+                hypervisorRegex,
+                os,
+                locationId,
+                hardwareId,
+                imageId,
+                imageDescriptionRegex,
+                imageNameRegex,
+                imageVersionRegex,
+                // might not be implement hashCode, so ignore
+//                imageCondition,
+//                imageChooserFunction,
+                is64bit,
+                locationId,
+                osArchitectureRegex,
+                osDescriptionRegex,
+                osNameRegex,
+                osVersionRegex,
+                minCores,
+                minRam,
+                minDisk,
+                options,
+                additionalOptions,
+                // might not implement hashCode, so ignore
+//                template,
+                0);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        AbstractPortableTemplateBuilder other = 
(AbstractPortableTemplateBuilder) obj;
+        if (!Objects.equal(additionalOptions, other.additionalOptions)) return 
false;
+        if (!Objects.equal(commands, other.commands)) return false;
+        if (!Objects.equal(locationId, other.locationId)) return false;
+        if (!Objects.equal(hardware, other.hardware)) return false;
+        if (!Objects.equal(hardwareId, other.hardwareId)) return false;
+        if (!Objects.equal(image, other.image)) return false;
+        if (!Objects.equal(imageId, other.imageId)) return false;
+        if (!Objects.equal(imageDescriptionRegex, 
other.imageDescriptionRegex)) return false;
+        if (!Objects.equal(imageNameRegex, other.imageNameRegex)) return false;
+        if (!Objects.equal(imageVersionRegex, other.imageVersionRegex)) return 
false;
+        if (!Objects.equal(imageCondition, other.imageCondition)) return false;
+        if (!Objects.equal(imageChooserFunction, other.imageChooserFunction)) 
return false;
+        if (!Objects.equal(os, other.os)) return false;
+        if (!Objects.equal(osArchitectureRegex, other.osArchitectureRegex)) 
return false;
+        if (!Objects.equal(osDescriptionRegex, other.osDescriptionRegex)) 
return false;
+        if (!Objects.equal(osNameRegex, other.osNameRegex)) return false;
+        if (!Objects.equal(osVersionRegex, other.osVersionRegex)) return false;
+        if (!Objects.equal(is64bit, other.is64bit)) return false;
+        if (!Objects.equal(hypervisorRegex, other.hypervisorRegex)) return 
false;
+        if (!Objects.equal(minCores, other.minCores)) return false;
+        if (!Objects.equal(minRam, other.minRam)) return false;
+        if (!Objects.equal(minDisk, other.minDisk)) return false;
+        if (!Objects.equal(options, other.options)) return false;
+        if (!Objects.equal(template, other.template)) return false;
+        return true;
+    }
+    
+    @Override
+    public String toString() {
+        return 
getClass().getSimpleName()+"["+makeNonTrivialArgumentsString()+"]";
+    }
+
+    protected String makeNonTrivialArgumentsString() {
+        String s =
+                  (hardware != null ? "hardware=" + hardware + ", " : "")
+                + (image != null ? "image=" + image + ", " : "")
+                + (template != null ? "template=" + template + ", " : "")
+                + (hypervisorRegex != null ? "hypervisorRegex="
+                        + hypervisorRegex + ", " : "")
+                + (os != null ? "os=" + os + ", " : "")
+                + (locationId != null ? "locationId=" + locationId + ", " : "")
+                + (imageId != null ? "imageId=" + imageId + ", " : "")
+                + (hardwareId != null ? "hardwareId=" + hardwareId + ", " : "")
+                + (osNameRegex != null ? "osNameRegex=" + osNameRegex + ", "
+                        : "")
+                + (osDescriptionRegex != null ? "osDescriptionRegex="
+                        + osDescriptionRegex + ", " : "")
+                + (osVersionRegex != null ? "osVersionRegex=" + osVersionRegex
+                        + ", " : "")
+                + (osArchitectureRegex != null ? "osArchictectureRegex="
+                        + osArchitectureRegex + ", " : "")
+                + (is64bit != null ? "is64bit=" + is64bit + ", " : "")
+                + (imageNameRegex != null ? "imageNameRegex=" + imageNameRegex
+                        + ", " : "")
+                + (imageDescriptionRegex != null ? "imageDescriptionRegex="
+                        + imageDescriptionRegex + ", " : "")
+                + (imageVersionRegex != null ? "imageVersionRegex="
+                        + imageVersionRegex + ", " : "")
+                + (imageCondition != null ? "imageCondition=" + imageCondition
+                        + ", " : "")
+                + (imageChooserFunction != null ? "imageChooserFunction=" + 
imageChooserFunction
+                        + ", " : "")
+                + (minCores != null ? "minCores=" + minCores + ", " : "")
+                + (minRam != null ? "minRam=" + minRam + ", " : "")
+                + (minDisk != null ? "minDisk=" + minDisk + ", " : "");
+        if (s.endsWith(", ")) s = s.substring(0, s.length()-2);
+        return s;
+    }    
+
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/PortableTemplateBuilder.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/PortableTemplateBuilder.java
 
b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/PortableTemplateBuilder.java
new file mode 100644
index 0000000..eaea03b
--- /dev/null
+++ 
b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/templates/PortableTemplateBuilder.java
@@ -0,0 +1,145 @@
+/*
+ * 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.jclouds.templates;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.domain.TemplateBuilderSpec;
+import org.jclouds.compute.options.TemplateOptions;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.primitives.Ints;
+
+
+public class PortableTemplateBuilder<T extends PortableTemplateBuilder<?>> 
extends AbstractPortableTemplateBuilder<T> {
+    
+    ComputeService svc;
+    List<TemplateOptions> additionalOptionalOptions = new 
ArrayList<TemplateOptions>();
+
+    @Override
+    public synchronized Template build() {
+        if (svc!=null) return newJcloudsTemplate(svc);
+        throw new IllegalStateException("Cannot build a portable template 
until a compute service is attached");
+    }
+    
+    public synchronized ComputeService attachComputeService(ComputeService 
svc) {
+        ComputeService old = this.svc;
+        this.svc = svc;
+        return old;
+    }
+
+    public TemplateBuilder newJcloudsTemplateBuilder(ComputeService svc) {
+        TemplateBuilder tb = svc.templateBuilder();
+        for (Function<TemplateBuilder,TemplateBuilder> c: commands) {
+            tb = c.apply(tb);
+        }
+        
+        tb.options(computeAggregatedOptions(true));
+        
+        return tb;
+    }
+
+    public Template newJcloudsTemplate(ComputeService svc) {
+        return newJcloudsTemplateBuilder(svc).build();
+    }
+
+    /** Adds template options which are used for building, but not for 
matching/filtering. 
+     * (eg tags added here will be set on any machine created by this template,
+     * but will not be required when matching this template to existing 
machines) */
+    @SuppressWarnings("unchecked")
+    public T addOptionalOptions(TemplateOptions options) {
+        additionalOptionalOptions.add(options);
+        return (T)this;
+    }
+    
+    protected TemplateOptions computeAggregatedOptions(boolean 
includeOptional) {
+        TemplateOptions result;
+        if (getOptions()!=null) result = getOptions().clone();
+        else result = new TemplateOptions();
+        if (includeOptional)
+            for (TemplateOptions moreOptions: getAdditionalOptionalOptions()) 
result = addTemplateOptions(result, moreOptions);
+        for (TemplateOptions moreOptions: getAdditionalOptions()) result = 
addTemplateOptions(result, moreOptions);
+        return result;
+    }
+    
+    public List<TemplateOptions> getAdditionalOptionalOptions() {
+        return ImmutableList.copyOf(additionalOptionalOptions);
+    }
+    
+    /** like TemplateOptions.copyTo but additive wrt arrays, collections, and 
maps,
+     * putting moreOptions in on top of / at the end of options.
+     * currently applies to inboundPorts, tags, and userMetadata. */
+    public static TemplateOptions addTemplateOptions(TemplateOptions options, 
TemplateOptions moreOptions) {
+        TemplateOptions result = options.clone();
+        moreOptions.copyTo(result);
+        
+        Set<String> tags = new LinkedHashSet<String>(options.getTags());
+        tags.addAll(moreOptions.getTags());
+        result.tags(tags);
+
+        Map<String,String> userMetadata = new 
LinkedHashMap<String,String>(options.getUserMetadata());
+        userMetadata.putAll(moreOptions.getUserMetadata());
+        result.userMetadata(userMetadata);
+        
+        Set<Integer> inboundPorts = new TreeSet<Integer>();
+        for (int port: options.getInboundPorts()) inboundPorts.add(port);
+        for (int port: moreOptions.getInboundPorts()) inboundPorts.add(port);
+        int[] inboundPortsArray = new int[inboundPorts.size()];
+        int i=0;
+        for (Iterator<Integer> portI=inboundPorts.iterator(); 
portI.hasNext();) {
+            inboundPortsArray[i++] = portI.next();
+        }
+        result.inboundPorts(inboundPortsArray);
+        
+        return result;
+    }
+
+    protected String makeNonTrivialArgumentsString() {
+        String s = super.makeNonTrivialArgumentsString();
+        TemplateOptions aggr = computeAggregatedOptions(false);
+        if (aggr.getInboundPorts().length>0) s = 
"ports="+Ints.asList(aggr.getInboundPorts())+(s!=null && s.length()>0 ? ", "+s 
: "");
+        if (!aggr.getUserMetadata().isEmpty()) s = 
"metadata="+aggr.getUserMetadata()+(s!=null && s.length()>0 ? ", "+s : "");
+        if (!aggr.getTags().isEmpty()) s = "tags="+aggr.getTags()+(s!=null && 
s.length()>0 ? ", "+s : "");
+        return s;
+    }
+    
+    @Override
+    public TemplateBuilder from(TemplateBuilderSpec spec) {
+        TemplateOptions options = new TemplateOptions();
+        addOptionalOptions(options);
+        TemplateBuilder result = spec.copyTo(this, options);
+        return result;
+    }
+
+    @Override
+    public TemplateBuilder from(String spec) {
+        return from(TemplateBuilderSpec.parse(spec));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtension.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtension.java
 
b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtension.java
new file mode 100644
index 0000000..dcb6b4c
--- /dev/null
+++ 
b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtension.java
@@ -0,0 +1,74 @@
+/*
+ * 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.jclouds.zone;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.location.Location;
+import org.apache.brooklyn.location.cloud.AbstractAvailabilityZoneExtension;
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.ec2.domain.AvailabilityZoneInfo;
+
+import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension;
+import org.apache.brooklyn.location.jclouds.JcloudsLocation;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+public class AwsAvailabilityZoneExtension extends 
AbstractAvailabilityZoneExtension implements AvailabilityZoneExtension {
+
+    private final JcloudsLocation loc;
+    
+    public AwsAvailabilityZoneExtension(ManagementContext managementContext, 
JcloudsLocation loc) {
+        super(managementContext);
+        this.loc = checkNotNull(loc, "loc");
+        checkArgument(loc.getProvider().equals("aws-ec2"), "provider not 
aws-ec2 (%s)", loc.getProvider());
+    }
+
+    @Override
+    protected List<Location> doGetAllSubLocations() {
+        List<Location> result = Lists.newArrayList();
+        Set<AvailabilityZoneInfo> zones = getAvailabilityZones();
+        for (AvailabilityZoneInfo zone : zones) {
+            result.add(newSubLocation(loc, zone));
+        }
+        return result;
+    }
+    
+    @Override
+    protected boolean isNameMatch(Location loc, Predicate<? super String> 
namePredicate) {
+        return namePredicate.apply(((JcloudsLocation)loc).getRegion());
+    }
+    
+    protected Set<AvailabilityZoneInfo> getAvailabilityZones() {
+        String regionName = loc.getRegion();
+        AWSEC2Api ec2Client = 
loc.getComputeService().getContext().unwrapApi(AWSEC2Api.class);
+        return 
ec2Client.getAvailabilityZoneAndRegionApi().get().describeAvailabilityZonesInRegion(regionName);
+    }
+    
+    protected JcloudsLocation newSubLocation(Location parent, 
AvailabilityZoneInfo zone) {
+        return 
loc.newSubLocation(ImmutableMap.of(JcloudsLocation.CLOUD_REGION_ID, 
zone.getZone()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/resources/META-INF/services/brooklyn.location.LocationResolver
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/resources/META-INF/services/brooklyn.location.LocationResolver
 
b/locations/jclouds/src/main/resources/META-INF/services/brooklyn.location.LocationResolver
deleted file mode 100644
index 5b1c084..0000000
--- 
a/locations/jclouds/src/main/resources/META-INF/services/brooklyn.location.LocationResolver
+++ /dev/null
@@ -1,2 +0,0 @@
-brooklyn.location.jclouds.JcloudsLocationResolver
-brooklyn.location.jclouds.JcloudsByonLocationResolver

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/main/resources/META-INF/services/org.apache.brooklyn.location.LocationResolver
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/resources/META-INF/services/org.apache.brooklyn.location.LocationResolver
 
b/locations/jclouds/src/main/resources/META-INF/services/org.apache.brooklyn.location.LocationResolver
new file mode 100644
index 0000000..e29b717
--- /dev/null
+++ 
b/locations/jclouds/src/main/resources/META-INF/services/org.apache.brooklyn.location.LocationResolver
@@ -0,0 +1,2 @@
+org.apache.brooklyn.location.jclouds.JcloudsLocationResolver
+org.apache.brooklyn.location.jclouds.JcloudsByonLocationResolver

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java
 
b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java
index dcce68a..eb1654e 100644
--- 
a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java
+++ 
b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreCleaner.java
@@ -29,9 +29,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import brooklyn.config.BrooklynProperties;
-import brooklyn.location.basic.LocationConfigKeys;
-import brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.location.jclouds.JcloudsLocation;
+import org.apache.brooklyn.location.basic.LocationConfigKeys;
+import org.apache.brooklyn.location.cloud.CloudLocationConfig;
+import org.apache.brooklyn.location.jclouds.JcloudsLocation;
 
 /** Utility for cleaning up after test leaks. Most should not leak of course, 
but if they do... */
 public class BlobStoreCleaner {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java
 
b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java
index c29bf79..6260a8c 100644
--- 
a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java
+++ 
b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java
@@ -44,10 +44,10 @@ import org.testng.annotations.Test;
 
 import brooklyn.config.BrooklynProperties;
 import brooklyn.entity.basic.Entities;
-import brooklyn.location.basic.LocationConfigKeys;
-import brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.location.jclouds.JcloudsLocation;
-import brooklyn.location.jclouds.JcloudsUtil;
+import org.apache.brooklyn.location.basic.LocationConfigKeys;
+import org.apache.brooklyn.location.cloud.CloudLocationConfig;
+import org.apache.brooklyn.location.jclouds.JcloudsLocation;
+import org.apache.brooklyn.location.jclouds.JcloudsUtil;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.http.HttpTool;
 import brooklyn.util.http.HttpToolResponse;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java
 
b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java
index f9ba3a9..0553fd0 100644
--- 
a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java
+++ 
b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreTest.java
@@ -36,10 +36,10 @@ import org.testng.annotations.Test;
 
 import brooklyn.config.BrooklynProperties;
 import brooklyn.entity.basic.Entities;
-import brooklyn.location.basic.LocationConfigKeys;
-import brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.location.jclouds.JcloudsLocation;
-import brooklyn.location.jclouds.JcloudsUtil;
+import org.apache.brooklyn.location.basic.LocationConfigKeys;
+import org.apache.brooklyn.location.cloud.CloudLocationConfig;
+import org.apache.brooklyn.location.jclouds.JcloudsLocation;
+import org.apache.brooklyn.location.jclouds.JcloudsUtil;
 import brooklyn.util.stream.Streams;
 import brooklyn.util.text.Identifiers;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java
 
b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java
index eaaf0f8..556c3c3 100644
--- 
a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java
+++ 
b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsExpect100ContinueTest.java
@@ -30,8 +30,8 @@ import org.testng.annotations.Test;
 
 import brooklyn.config.BrooklynProperties;
 import brooklyn.entity.basic.Entities;
-import brooklyn.location.jclouds.JcloudsLocation;
-import brooklyn.location.jclouds.JcloudsUtil;
+import org.apache.brooklyn.location.jclouds.JcloudsLocation;
+import org.apache.brooklyn.location.jclouds.JcloudsUtil;
 import brooklyn.util.text.Identifiers;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java
 
b/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java
deleted file mode 100644
index d84ce5c..0000000
--- 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java
+++ /dev/null
@@ -1,158 +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 com.google.common.base.Preconditions.checkNotNull;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.entity.basic.Entities;
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.util.exceptions.CompoundRuntimeException;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-
-public class AbstractJcloudsLiveTest {
-
-    private static final Logger LOG = 
LoggerFactory.getLogger(AbstractJcloudsLiveTest.class);
-
-    public static final String BROOKLYN_PROPERTIES_PREFIX = 
"brooklyn.location.jclouds.";
-    public static final String BROOKLYN_PROPERTIES_LEGACY_PREFIX = 
"brooklyn.jclouds.";
-    
-    public static final String AWS_EC2_PROVIDER = "aws-ec2";
-    public static final String AWS_EC2_MICRO_HARDWARE_ID = "t1.micro";
-    public static final String AWS_EC2_SMALL_HARDWARE_ID = "m1.small";
-    public static final String AWS_EC2_EUWEST_REGION_NAME = "eu-west-1";
-    public static final String AWS_EC2_USEAST_REGION_NAME = "us-east-1";
-
-    public static final String RACKSPACE_PROVIDER = 
"rackspace-cloudservers-uk";
-    
-    public static final String SOFTLAYER_PROVIDER = "softlayer";
-    public static final String SOFTLAYER_AMS01_REGION_NAME = "ams01";
-    
-    protected BrooklynProperties brooklynProperties;
-    protected LocalManagementContext managementContext;
-    
-    protected List<JcloudsSshMachineLocation> machines;
-    protected JcloudsLocation jcloudsLocation;
-    
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-        machines = Lists.newCopyOnWriteArrayList();
-        managementContext = newManagementContext();
-        
-        // Don't let any defaults from brooklyn.properties (except 
credentials) interfere with test
-        brooklynProperties = managementContext.getBrooklynProperties();
-        stripBrooklynProperties(brooklynProperties);
-    }
-
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        List<Exception> exceptions = Lists.newArrayList();
-        try {
-            if (machines != null) {
-                for (JcloudsSshMachineLocation machine : machines) {
-                    try {
-                        releaseMachine(machine);
-                    } catch (Exception e) {
-                        LOG.warn("Error releasing machine "+machine+"; 
continuing...", e);
-                        exceptions.add(e);
-                    }
-                }
-                machines.clear();
-            }
-        } finally {
-            try {
-                if (managementContext != null) 
Entities.destroyAll(managementContext);
-            } catch (Exception e) {
-                LOG.warn("Error destroying management context", e);
-                exceptions.add(e);
-            }
-        }
-        
-        // TODO Debate about whether to:
-        //  - use destroyAllCatching (i.e. not propagating exception)
-        //    Benefit is that other tests in class will subsequently be run, 
rather than bailing out.
-        //  - propagate exceptions from tearDown
-        //    Benefit is that we don't hide errors; release(...) etc should 
not be throwing exceptions.
-        if (exceptions.size() > 0) {
-            throw new CompoundRuntimeException("Error in tearDown of 
"+getClass(), exceptions);
-        }
-    }
-
-    protected LocalManagementContext newManagementContext() {
-        // loads properties, by default, but not OSGi or anything else
-        return 
LocalManagementContextForTests.builder(true).useDefaultProperties().build();
-    }
-    
-    protected void stripBrooklynProperties(BrooklynProperties props) {
-        // remove all location properties except for identity and credential
-        // (so key, scripts, etc settings don't interfere with tests) 
-        for (String key : 
ImmutableSet.copyOf(props.asMapWithStringKeys().keySet())) {
-            if (key.startsWith(BROOKLYN_PROPERTIES_PREFIX) && 
!(key.endsWith("identity") || key.endsWith("credential"))) {
-                props.remove(key);
-            }
-            if (key.startsWith(BROOKLYN_PROPERTIES_LEGACY_PREFIX) && 
!(key.endsWith("identity") || key.endsWith("credential"))) {
-                props.remove(key);
-            }
-            
-            // Also removes scriptHeader (e.g. if doing `. ~/.bashrc` and `. 
~/.profile`, then that can cause "stdin: is not a tty")
-            if (key.startsWith("brooklyn.ssh")) {
-                props.remove(key);
-            }
-        }
-    }
-    
-    protected void assertSshable(SshMachineLocation machine) {
-        int result = machine.execScript("simplecommand", 
ImmutableList.of("true"));
-        assertEquals(result, 0);
-    }
-
-    // Use this utility method to ensure machines are released on tearDown
-    protected JcloudsSshMachineLocation obtainMachine(Map<?, ?> conf) throws 
Exception {
-        assertNotNull(jcloudsLocation);
-        JcloudsSshMachineLocation result = 
(JcloudsSshMachineLocation)jcloudsLocation.obtain(conf);
-        machines.add(checkNotNull(result, "result"));
-        return result;
-    }
-
-    protected JcloudsSshMachineLocation obtainMachine() throws Exception {
-        return obtainMachine(ImmutableMap.of());
-    }
-    
-    protected void releaseMachine(JcloudsSshMachineLocation machine) {
-        assertNotNull(jcloudsLocation);
-        machines.remove(machine);
-        jcloudsLocation.release(machine);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java
 
b/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java
deleted file mode 100644
index 3b8a4f4..0000000
--- 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/AbstractJcloudsStubbedLiveTest.java
+++ /dev/null
@@ -1,133 +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 java.util.List;
-import java.util.Set;
-
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.NodeMetadata.Status;
-import org.jclouds.compute.domain.NodeMetadataBuilder;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.domain.LoginCredentials;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.BeforeMethod;
-
-import brooklyn.location.jclouds.ComputeServiceRegistry;
-import brooklyn.location.jclouds.ComputeServiceRegistryImpl;
-import brooklyn.location.jclouds.JcloudsLocation;
-import brooklyn.location.jclouds.JcloudsLocationConfig;
-import brooklyn.util.config.ConfigBag;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-/**
- * The VM creation is stubbed out, but it still requires live access (i.e. 
real account credentials)
- * to generate the template etc.
- * 
- * We supply a ComputeServiceRegistry that delegates to the real instance for 
everything except
- * VM creation and deletion. For those operations, it delegates to a 
NodeCreator that 
- * returns a dummy NodeMetadata, recording all calls made to it.
- */
-public abstract class AbstractJcloudsStubbedLiveTest extends 
AbstractJcloudsLiveTest {
-
-    @SuppressWarnings("unused")
-    private static final Logger LOG = 
LoggerFactory.getLogger(AbstractJcloudsStubbedLiveTest.class);
-
-    public static final String LOCATION_SPEC = "jclouds:" + SOFTLAYER_PROVIDER 
+ ":" + SOFTLAYER_AMS01_REGION_NAME;
-    
-    public static abstract class NodeCreator {
-        public final List<NodeMetadata> created = 
Lists.newCopyOnWriteArrayList();
-        public final List<String> destroyed = Lists.newCopyOnWriteArrayList();
-        
-        public Set<? extends NodeMetadata> createNodesInGroup(String group, 
int count, Template template) throws RunNodesException {
-            Set<NodeMetadata> result = Sets.newLinkedHashSet();
-            for (int i = 0; i < count; i++) {
-                NodeMetadata node = newNode(group, template);
-                created.add(node);
-                result.add(node);
-            }
-            return result;
-        }
-        public void destroyNode(String id) {
-            destroyed.add(id);
-        }
-        protected abstract NodeMetadata newNode(String group, Template 
template);
-    }
-    
-    public static class StubbedComputeService extends DelegatingComputeService 
{
-        private final NodeCreator nodeCreator;
-        
-        public StubbedComputeService(ComputeService delegate, NodeCreator 
nodeCreator) {
-            super(delegate);
-            this.nodeCreator = nodeCreator;
-        }
-        @Override
-        public Set<? extends NodeMetadata> createNodesInGroup(String group, 
int count, Template template) throws RunNodesException {
-            return nodeCreator.createNodesInGroup(group, count, template);
-        }
-        @Override
-        public void destroyNode(String id) {
-            nodeCreator.destroyNode(id);
-        }
-        @Override
-        public Set<? extends NodeMetadata> createNodesInGroup(String group, 
int count) {
-            throw new UnsupportedOperationException();
-        }
-        @Override
-        public Set<? extends NodeMetadata> createNodesInGroup(String group, 
int count, TemplateOptions templateOptions) {
-            throw new UnsupportedOperationException();
-        }
-        @Override
-        public Set<? extends NodeMetadata> 
destroyNodesMatching(Predicate<NodeMetadata> filter) {
-            throw new UnsupportedOperationException();
-        }
-    }
-    
-    protected NodeCreator nodeCreator;
-    
-    @BeforeMethod(alwaysRun=true)
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        nodeCreator = newNodeCreator();
-        ComputeServiceRegistry computeServiceRegistry = new 
ComputeServiceRegistry() {
-            @Override
-            public ComputeService findComputeService(ConfigBag conf, boolean 
allowReuse) {
-                ComputeService delegate = 
ComputeServiceRegistryImpl.INSTANCE.findComputeService(conf, allowReuse);
-                return new StubbedComputeService(delegate, nodeCreator);
-            }
-        };
-        jcloudsLocation = (JcloudsLocation) 
managementContext.getLocationRegistry().resolve(
-                LOCATION_SPEC, 
-                ImmutableMap.of(
-                        JcloudsLocationConfig.COMPUTE_SERVICE_REGISTRY, 
computeServiceRegistry,
-                        JcloudsLocationConfig.WAIT_FOR_SSHABLE, "false"));
-    }
-    
-    protected abstract NodeCreator newNodeCreator();
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/BailOutJcloudsLocation.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/BailOutJcloudsLocation.java
 
b/locations/jclouds/src/test/java/brooklyn/location/jclouds/BailOutJcloudsLocation.java
deleted file mode 100644
index d952c5b..0000000
--- 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/BailOutJcloudsLocation.java
+++ /dev/null
@@ -1,188 +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 java.util.Collections;
-import java.util.Map;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.compute.domain.Template;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.reflect.TypeToken;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.location.LocationSpec;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.CompoundRuntimeException;
-import brooklyn.util.exceptions.Exceptions;
-
-public class BailOutJcloudsLocation extends JcloudsLocation {
-
-    // Don't care which image; not actually provisioning
-    private static final String US_EAST_IMAGE_ID = "us-east-1/ami-7d7bfc14";
-    public static final RuntimeException BAIL_OUT_FOR_TESTING = new 
RuntimeException("early termination for test");
-
-    public static final ConfigKey<Function<ConfigBag, Void>> 
BUILD_TEMPLATE_INTERCEPTOR = ConfigKeys.newConfigKey(
-            new TypeToken<Function<ConfigBag, Void>>() {},
-            "buildtemplateinterceptor");
-
-    public static final ConfigKey<Boolean> BUILD_TEMPLATE = 
ConfigKeys.newBooleanConfigKey(
-            "buildtemplate");
-
-    private static final long serialVersionUID = -3373789512935057842L;
-
-    ConfigBag lastConfigBag;
-    Template template;
-
-    public BailOutJcloudsLocation() {
-        super();
-    }
-
-    public BailOutJcloudsLocation(Map<?, ?> conf) {
-        super(conf);
-    }
-
-    @Override
-    public Template buildTemplate(ComputeService computeService, ConfigBag 
config) {
-        lastConfigBag = config;
-        if (getConfig(BUILD_TEMPLATE_INTERCEPTOR) != null) {
-            getConfig(BUILD_TEMPLATE_INTERCEPTOR).apply(config);
-        }
-        if (Boolean.TRUE.equals(getConfig(BUILD_TEMPLATE))) {
-            template = super.buildTemplate(computeService, config);
-        }
-        throw BAIL_OUT_FOR_TESTING;
-    }
-
-    public Template getTemplate() {
-        return template;
-    }
-
-    public void tryObtain() {
-        tryObtain(Collections.emptyMap());
-    }
-
-    public void tryObtain(Map<?, ?> flags) {
-        tryObtainAndCheck(flags, Predicates.alwaysTrue());
-    }
-
-    public void tryObtainAndCheck(Map<?, ?> flags, Predicate<? super 
ConfigBag> test) {
-        try {
-            obtain(flags);
-        } catch (Exception e) {
-            if (e == BAIL_OUT_FOR_TESTING || e.getCause() == 
BAIL_OUT_FOR_TESTING
-                    || (e instanceof CompoundRuntimeException && 
((CompoundRuntimeException) e).getAllCauses().contains(BAIL_OUT_FOR_TESTING))) {
-                test.apply(lastConfigBag);
-            } else {
-                throw Exceptions.propagate(e);
-            }
-        }
-    }
-
-    @Override
-    @VisibleForTesting
-    public UserCreation createUserStatements(@Nullable Image image, ConfigBag 
config) {
-        return super.createUserStatements(image, config);
-    }
-
-
-    public static BailOutJcloudsLocation 
newBailOutJcloudsLocation(ManagementContext mgmt) {
-        return newBailOutJcloudsLocation(mgmt, Collections.<ConfigKey<?>, 
Object>emptyMap());
-    }
-
-    public static BailOutJcloudsLocation 
newBailOutJcloudsLocation(ManagementContext mgmt, Map<ConfigKey<?>, ?> config) {
-        Map<ConfigKey<?>, ?> allConfig = MutableMap.<ConfigKey<?>, 
Object>builder()
-                .put(IMAGE_ID, "bogus")
-                .put(CLOUD_PROVIDER, "aws-ec2")
-                .put(ACCESS_IDENTITY, "bogus")
-                .put(CLOUD_REGION_ID, "bogus")
-                .put(ACCESS_CREDENTIAL, "bogus")
-                .put(USER, "fred")
-                .put(MIN_RAM, 16)
-                .put(JcloudsLocation.MACHINE_CREATE_ATTEMPTS, 1)
-                .putAll(config)
-                .build();
-        return mgmt.getLocationManager().createLocation(
-                
LocationSpec.create(BailOutJcloudsLocation.class).configure(allConfig));
-    }
-
-
-    // todo better name
-
-    /** As {@link BailOutJcloudsLocation}, counting the number of {@link 
#buildTemplate} calls. */
-    public static class CountingBailOutJcloudsLocation extends 
BailOutJcloudsLocation {
-        private static final long serialVersionUID = 2433684033045735773L;
-        int buildTemplateCount = 0;
-        @Override
-        public Template buildTemplate(ComputeService computeService, ConfigBag 
config) {
-            buildTemplateCount++;
-            return super.buildTemplate(computeService, config);
-        }
-    }
-
-    public static CountingBailOutJcloudsLocation 
newCountingBailOutJcloudsLocation(ManagementContext mgmt, Map flags) {
-        LocationSpec<CountingBailOutJcloudsLocation> spec = 
LocationSpec.create(CountingBailOutJcloudsLocation.class)
-                .configure(flags);
-        return mgmt.getLocationManager().createLocation(spec);
-    }
-
-    /** @see #newBailOutJcloudsLocationForLiveTest(LocalManagementContext, 
Map)} */
-    public static BailOutJcloudsLocation 
newBailOutJcloudsLocationForLiveTest(LocalManagementContext mgmt) {
-        return newBailOutJcloudsLocationForLiveTest(mgmt, 
Collections.<ConfigKey<?>, Object>emptyMap());
-    }
-
-    /**
-     * Takes identity and access credential from management context's Brooklyn 
properties and sets
-     * inbound ports to [22, 80, 9999].
-     */
-    public static BailOutJcloudsLocation 
newBailOutJcloudsLocationForLiveTest(LocalManagementContext mgmt, 
Map<ConfigKey<?>, ?> config) {
-        BrooklynProperties brooklynProperties = mgmt.getBrooklynProperties();
-        String identity = (String) 
brooklynProperties.get("brooklyn.location.jclouds.aws-ec2.identity");
-        if (identity == null) identity = (String) 
brooklynProperties.get("brooklyn.jclouds.aws-ec2.identity");
-        String credential = (String) 
brooklynProperties.get("brooklyn.location.jclouds.aws-ec2.credential");
-        if (credential == null) credential = (String) 
brooklynProperties.get("brooklyn.jclouds.aws-ec2.credential");
-
-        Map<ConfigKey<?>, ?> allConfig = MutableMap.<ConfigKey<?>, 
Object>builder()
-                .put(CLOUD_PROVIDER, AbstractJcloudsLiveTest.AWS_EC2_PROVIDER)
-                .put(CLOUD_REGION_ID, 
AbstractJcloudsLiveTest.AWS_EC2_USEAST_REGION_NAME)
-                .put(IMAGE_ID, US_EAST_IMAGE_ID) // so Brooklyn does not 
attempt to load all EC2 images
-                .put(ACCESS_IDENTITY, identity)
-                .put(ACCESS_CREDENTIAL, credential)
-                .put(INBOUND_PORTS, "[22, 80, 9999]")
-                .put(BUILD_TEMPLATE, true)
-                .putAll(config)
-                .build();
-
-        return newBailOutJcloudsLocation(mgmt, allConfig);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java
 
b/locations/jclouds/src/test/java/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java
deleted file mode 100644
index 7a52f04..0000000
--- 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.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;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.location.basic.SshMachineLocation;
-import brooklyn.location.jclouds.pool.MachinePoolPredicates;
-import brooklyn.location.jclouds.pool.MachineSet;
-import brooklyn.location.jclouds.pool.ReusableMachineTemplate;
-import brooklyn.management.internal.LocalManagementContext;
-
-public class BrooklynMachinePoolLiveTest {
-
-    public static final Logger log = 
LoggerFactory.getLogger(BrooklynMachinePoolLiveTest.class);
-    
-    public static class SamplePool extends BrooklynMachinePool {
-        public SamplePool(JcloudsLocation l) {
-            super(l);
-        }
-
-        public final static ReusableMachineTemplate 
-            USUAL_VM = 
-                new ReusableMachineTemplate("usual").templateOwnedByMe().
-                tagOptional("tagForUsualVm").
-                metadataOptional("metadataForUsualVm", "12345").
-                minRam(1024).minCores(2);
-
-        public final static ReusableMachineTemplate 
-            ANYONE_NOT_TINY_VM = 
-                new ReusableMachineTemplate("anyone").
-                minRam(512).minCores(1).strict(false);
-
-        public static final ReusableMachineTemplate 
-            VM_LARGE1 = 
-                new ReusableMachineTemplate("vm.large1").templateOwnedByMe().
-                minRam(16384).minCores(4),
-            VM_SMALL1 = 
-                new 
ReusableMachineTemplate("vm.small1").templateOwnedByMe().smallest();
-        
-        { registerTemplates(USUAL_VM, ANYONE_NOT_TINY_VM, VM_LARGE1, 
VM_SMALL1); }
-    }
-
-
-    private LocalManagementContext managementContext;
-    
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-        managementContext = new LocalManagementContext();
-    }
-    
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        if (managementContext != null) managementContext.terminate();
-    }
-    
-    @Test(groups="Live")
-    public void buildClaimAndDestroy() {
-        SamplePool p = new SamplePool(resolve("aws-ec2:us-west-1"));
-        log.info("buildClaimAndDestroy: created pool");
-        p.refresh();
-        log.info("buildClaimAndDestroy: refreshed pool");
-        p.ensureExists(2, SamplePool.USUAL_VM);
-        log.info("buildClaimAndDestroy: ensure have 2");
-        SshMachineLocation l = p.obtain(SamplePool.USUAL_VM);
-        Assert.assertNotNull(l);
-        log.info("buildClaimAndDestroy: claimed 1");
-        MachineSet unclaimedUsual = 
p.unclaimed(MachinePoolPredicates.matching(SamplePool.USUAL_VM));
-        log.info("buildClaimAndDestroy: unclaimed now "+unclaimedUsual);
-        Assert.assertTrue(!unclaimedUsual.isEmpty(), "should have been 
unclaimed machines (can fail if there are some we cannot connect to, ie 
blacklisted)");
-        p.destroy(unclaimedUsual);
-        p.destroy(l);
-        unclaimedUsual = 
p.unclaimed(MachinePoolPredicates.matching(SamplePool.USUAL_VM));
-        log.info("buildClaimAndDestroy: destroyed, unclaimed now 
"+unclaimedUsual);
-        log.info("end");
-    }
-    
-
-    private JcloudsLocation resolve(String spec) {
-        return (JcloudsLocation) 
managementContext.getLocationRegistry().resolve(new 
JcloudsLocationResolver().getPrefix() + ":" + spec);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java
 
b/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java
deleted file mode 100644
index 62f621e..0000000
--- 
a/locations/jclouds/src/test/java/brooklyn/location/jclouds/DelegatingComputeService.java
+++ /dev/null
@@ -1,229 +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 java.util.Map;
-import java.util.Set;
-
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.ComputeServiceContext;
-import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.RunScriptOnNodesException;
-import org.jclouds.compute.domain.ComputeMetadata;
-import org.jclouds.compute.domain.ExecResponse;
-import org.jclouds.compute.domain.Hardware;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.domain.TemplateBuilder;
-import org.jclouds.compute.extensions.ImageExtension;
-import org.jclouds.compute.extensions.SecurityGroupExtension;
-import org.jclouds.compute.options.RunScriptOptions;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.domain.Location;
-import org.jclouds.scriptbuilder.domain.Statement;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.util.concurrent.ListenableFuture;
-
-public class DelegatingComputeService implements ComputeService {
-
-    private final ComputeService delegate;
-    
-    public DelegatingComputeService(ComputeService delegate) {
-        this.delegate = delegate;
-    }
-    
-    @Override
-    public ComputeServiceContext getContext() {
-        return delegate.getContext();
-    }
-
-    @Override
-    public TemplateBuilder templateBuilder() {
-        return delegate.templateBuilder();
-    }
-
-    @Override
-    public TemplateOptions templateOptions() {
-        return delegate.templateOptions();
-    }
-
-    @Override
-    public Set<? extends Hardware> listHardwareProfiles() {
-        return delegate.listHardwareProfiles();
-    }
-
-    @Override
-    public Set<? extends Image> listImages() {
-        return delegate.listImages();
-    }
-
-    @Override
-    public Image getImage(String id) {
-        return delegate.getImage(id);
-    }
-
-    @Override
-    public Set<? extends ComputeMetadata> listNodes() {
-        return delegate.listNodes();
-    }
-
-    @Override
-    public Set<? extends NodeMetadata> listNodesByIds(Iterable<String> ids) {
-        return delegate.listNodesByIds(ids);
-    }
-
-    @Override
-    public Set<? extends Location> listAssignableLocations() {
-        return delegate.listAssignableLocations();
-    }
-
-    @Override
-    public Set<? extends NodeMetadata> createNodesInGroup(String group, int 
count, Template template) throws RunNodesException {
-        return delegate.createNodesInGroup(group, count, template);
-    }
-
-    @Override
-    public Set<? extends NodeMetadata> createNodesInGroup(String group, int 
count, TemplateOptions templateOptions)
-            throws RunNodesException {
-        return delegate.createNodesInGroup(group, count, templateOptions);
-    }
-
-    @Override
-    public Set<? extends NodeMetadata> createNodesInGroup(String group, int 
count) throws RunNodesException {
-        return delegate.createNodesInGroup(group, count);
-    }
-
-    @Override
-    public void resumeNode(String id) {
-        delegate.resumeNode(id);
-    }
-
-    @Override
-    public Set<? extends NodeMetadata> 
resumeNodesMatching(Predicate<NodeMetadata> filter) {
-        return delegate.resumeNodesMatching(filter);
-    }
-
-    @Override
-    public void suspendNode(String id) {
-        delegate.suspendNode(id);
-    }
-
-    @Override
-    public Set<? extends NodeMetadata> 
suspendNodesMatching(Predicate<NodeMetadata> filter) {
-        return delegate.suspendNodesMatching(filter);
-    }
-
-    @Override
-    public void destroyNode(String id) {
-        delegate.destroyNode(id);
-    }
-
-    @Override
-    public Set<? extends NodeMetadata> 
destroyNodesMatching(Predicate<NodeMetadata> filter) {
-        return delegate.destroyNodesMatching(filter);
-    }
-
-    @Override
-    public void rebootNode(String id) {
-        delegate.rebootNode(id);
-    }
-
-    @Override
-    public Set<? extends NodeMetadata> 
rebootNodesMatching(Predicate<NodeMetadata> filter) {
-        return delegate.rebootNodesMatching(filter);
-    }
-
-    @Override
-    public NodeMetadata getNodeMetadata(String id) {
-        return delegate.getNodeMetadata(id);
-    }
-
-    @Override
-    public Set<? extends NodeMetadata> 
listNodesDetailsMatching(Predicate<ComputeMetadata> filter) {
-        return delegate.listNodesDetailsMatching(filter);
-    }
-
-    @Override
-    public Map<? extends NodeMetadata, ExecResponse> 
runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript)
-            throws RunScriptOnNodesException {
-        return delegate.runScriptOnNodesMatching(filter, runScript);
-    }
-
-    @Override
-    public Map<? extends NodeMetadata, ExecResponse> 
runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript)
-            throws RunScriptOnNodesException {
-        return delegate.runScriptOnNodesMatching(filter, runScript);
-    }
-
-    @Override
-    public Map<? extends NodeMetadata, ExecResponse> 
runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
-            String runScript, RunScriptOptions options) throws 
RunScriptOnNodesException {
-        return delegate.runScriptOnNodesMatching(filter, runScript, options);
-    }
-
-    @Override
-    public Map<? extends NodeMetadata, ExecResponse> 
runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
-            Statement runScript, RunScriptOptions options) throws 
RunScriptOnNodesException {
-        return delegate.runScriptOnNodesMatching(filter, runScript, options);
-    }
-
-    @Override
-    public ExecResponse runScriptOnNode(String id, Statement runScript, 
RunScriptOptions options) {
-        return delegate.runScriptOnNode(id, runScript, options);
-    }
-
-    @Override
-    public ListenableFuture<ExecResponse> submitScriptOnNode(String id, String 
runScript, RunScriptOptions options) {
-        return delegate.submitScriptOnNode(id, runScript, options);
-    }
-
-    @Override
-    public ListenableFuture<ExecResponse> submitScriptOnNode(String id, 
Statement runScript, RunScriptOptions options) {
-        return delegate.submitScriptOnNode(id, runScript, options);
-    }
-
-    @Override
-    public ExecResponse runScriptOnNode(String id, Statement runScript) {
-        return delegate.runScriptOnNode(id, runScript);
-    }
-
-    @Override
-    public ExecResponse runScriptOnNode(String id, String runScript, 
RunScriptOptions options) {
-        return delegate.runScriptOnNode(id, runScript, options);
-    }
-
-    @Override
-    public ExecResponse runScriptOnNode(String id, String runScript) {
-        return delegate.runScriptOnNode(id, runScript);
-    }
-
-    @Override
-    public Optional<ImageExtension> getImageExtension() {
-        return delegate.getImageExtension();
-    }
-
-    @Override
-    public Optional<SecurityGroupExtension> getSecurityGroupExtension() {
-        return delegate.getSecurityGroupExtension();
-    }
-
-}

Reply via email to