You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2016/02/18 10:57:53 UTC

jclouds-labs git commit: Refactored locations to not rely on existing DataCenters

Repository: jclouds-labs
Updated Branches:
  refs/heads/master 7b21c2e6a -> 7b8adc624


Refactored locations to not rely on existing DataCenters


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/7b8adc62
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/7b8adc62
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/7b8adc62

Branch: refs/heads/master
Commit: 7b8adc624e7c61381e3bf8e1145f36553bf0f8b2
Parents: 7b21c2e
Author: Ignasi Barrera <na...@apache.org>
Authored: Wed Feb 17 15:53:30 2016 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu Feb 18 10:48:00 2016 +0100

----------------------------------------------------------------------
 profitbricks/README.md                          |   4 +-
 .../ProfitBricksProviderMetadata.java           |  20 +++-
 .../ProfitBricksComputeServiceAdapter.java      |  52 +++------
 .../ProfitBricksTemplateBuilderImpl.java        | 101 -----------------
 ...ProfitBricksComputeServiceContextModule.java |  34 ++----
 .../compute/function/DataCenterToLocation.java  |  54 ---------
 .../compute/function/LocationToLocation.java    |  47 --------
 .../compute/function/ProvisionableToImage.java  |  29 +++--
 .../compute/function/ServerToNodeMetadata.java  |  42 +++----
 .../strategy/AssignDataCenterToTemplate.java    | 110 +++++++++++++++++++
 .../strategy/TemplateWithDataCenter.java        | 107 ++++++++++++++++++
 .../ProfitBricksComputeServiceLiveTest.java     |  77 +------------
 .../function/DataCenterToLocationTest.java      |  77 -------------
 .../function/LocationToLocationTest.java        |  62 -----------
 .../function/ProvisionableToImageTest.java      |  52 +++++----
 .../function/ServerToNodeMetadataTest.java      |  68 ++++++++----
 16 files changed, 375 insertions(+), 561 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/README.md
----------------------------------------------------------------------
diff --git a/profitbricks/README.md b/profitbricks/README.md
index 09c367a..67db8dd 100644
--- a/profitbricks/README.md
+++ b/profitbricks/README.md
@@ -53,11 +53,9 @@ Template template = compute.templateBuilder()
 	
 compute.createNodesInGroup( "cluster1", 1, template );
 ```
-> If no `locationId` is specified in the template, jclouds will look for a `DataCenter` that is of same scope as the `Image`.
-
 
 ## Limitations
 
 - There's no direct way of specifying arbitrary number of cores, RAM size, and storage size via the compute interface, at least until after [JCLOUDS-482](https://issues.apache.org/jira/browse/JCLOUDS-482) is resolved. The adapter uses a predefined list hardware profiles instead.
 
-> Take note that these features are still accessible by *unwraping* the ProfitBricks API, but this'll reduce portability of your code. See [Concepts](https://jclouds.apache.org/start/concepts/).
\ No newline at end of file
+> Take note that these features are still accessible by *unwraping* the ProfitBricks API, but this'll reduce portability of your code. See [Concepts](https://jclouds.apache.org/start/concepts/).

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksProviderMetadata.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksProviderMetadata.java b/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksProviderMetadata.java
index ec7fc9a..ba8b9d4 100644
--- a/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksProviderMetadata.java
+++ b/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksProviderMetadata.java
@@ -20,18 +20,23 @@ import static org.jclouds.Constants.PROPERTY_SO_TIMEOUT;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONE;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONES;
 import static org.jclouds.profitbricks.config.ProfitBricksComputeProperties.POLL_INITIAL_PERIOD;
 import static org.jclouds.profitbricks.config.ProfitBricksComputeProperties.POLL_MAX_PERIOD;
 import static org.jclouds.profitbricks.config.ProfitBricksComputeProperties.TIMEOUT_DATACENTER_AVAILABLE;
 
-import com.google.auto.service.AutoService;
-
 import java.net.URI;
 import java.util.Properties;
 
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.providers.internal.BaseProviderMetadata;
 
+import com.google.auto.service.AutoService;
+
 @AutoService(ProviderMetadata.class)
 public class ProfitBricksProviderMetadata extends BaseProviderMetadata {
 
@@ -54,6 +59,16 @@ public class ProfitBricksProviderMetadata extends BaseProviderMetadata {
 
    public static Properties defaultProperties() {
       Properties properties = ProfitBricksApiMetadata.defaultProperties();
+      
+      properties.setProperty(PROPERTY_REGIONS, "de,us");
+      properties.setProperty(PROPERTY_REGION + ".de.zones", "de/fkb,de/fra");
+      properties.setProperty(PROPERTY_REGION + ".us.zones", "us/las,us/lasdev");
+      properties.setProperty(PROPERTY_ZONES, "de/fkb,de/fra,us/las,us/lasdev");
+      properties.setProperty(PROPERTY_ZONE + ".de/fkb." + ISO3166_CODES, "DE-BW");
+      properties.setProperty(PROPERTY_ZONE + ".de/fra." + ISO3166_CODES, "DE-HE");
+      properties.setProperty(PROPERTY_ZONE + ".us/las." + ISO3166_CODES, "US-NV");
+      properties.setProperty(PROPERTY_ZONE + ".us/lasdebv." + ISO3166_CODES, "US-NV");
+      
       properties.put(TIMEOUT_DATACENTER_AVAILABLE, 30L * 60L); // 30 minutes
       properties.put(POLL_INITIAL_PERIOD, 5L);
       properties.put(POLL_MAX_PERIOD, 60L);
@@ -79,6 +94,7 @@ public class ProfitBricksProviderMetadata extends BaseProviderMetadata {
                  .name("ProfitBricks Cloud Compute 2.0")
                  .homepage(URI.create("http://www.profitbricks.com"))
                  .console(URI.create("https://my.profitbricks.com/dashboard/dcdr2/"))
+                 .iso3166Codes("DE-BW", "DE-HE", "US-NV")
                  .linkedServices("profitbricks")
                  .apiMetadata(new ProfitBricksApiMetadata())
                  .defaultProperties(ProfitBricksProviderMetadata.defaultProperties());

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java
index 68a7097..fe02c41 100644
--- a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java
+++ b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java
@@ -47,18 +47,18 @@ import org.jclouds.domain.LocationScope;
 import org.jclouds.domain.LoginCredentials;
 import org.jclouds.logging.Logger;
 import org.jclouds.profitbricks.ProfitBricksApi;
+import org.jclouds.profitbricks.compute.concurrent.ProvisioningJob;
+import org.jclouds.profitbricks.compute.concurrent.ProvisioningManager;
+import org.jclouds.profitbricks.compute.function.ProvisionableToImage;
+import org.jclouds.profitbricks.compute.strategy.TemplateWithDataCenter;
 import org.jclouds.profitbricks.domain.AvailabilityZone;
 import org.jclouds.profitbricks.domain.DataCenter;
 import org.jclouds.profitbricks.domain.Image;
+import org.jclouds.profitbricks.domain.Provisionable;
 import org.jclouds.profitbricks.domain.Server;
+import org.jclouds.profitbricks.domain.Snapshot;
 import org.jclouds.profitbricks.domain.Storage;
-import org.jclouds.profitbricks.features.DataCenterApi;
 import org.jclouds.profitbricks.features.ServerApi;
-import org.jclouds.profitbricks.compute.concurrent.ProvisioningJob;
-import org.jclouds.profitbricks.compute.concurrent.ProvisioningManager;
-import org.jclouds.profitbricks.compute.function.ProvisionableToImage;
-import org.jclouds.profitbricks.domain.Snapshot;
-import org.jclouds.profitbricks.domain.Provisionable;
 import org.jclouds.profitbricks.util.Passwords;
 import org.jclouds.rest.ResourceNotFoundException;
 
@@ -74,7 +74,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.inject.Inject;
 
 @Singleton
-public class ProfitBricksComputeServiceAdapter implements ComputeServiceAdapter<Server, Hardware, Provisionable, DataCenter> {
+public class ProfitBricksComputeServiceAdapter implements ComputeServiceAdapter<Server, Hardware, Provisionable, Location> {
 
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
@@ -100,12 +100,16 @@ public class ProfitBricksComputeServiceAdapter implements ComputeServiceAdapter<
       this.jobFactory = jobFactory;
       this.provisioningManager = provisioningManager;
    }
-
+   
    @Override
    public NodeAndInitialCredentials<Server> createNodeWithGroupEncodedIntoName(String group, String name, Template template) {
-      Location location = template.getLocation();
-      checkArgument(location.getScope() == LocationScope.ZONE, "Template must use a ZONE-scoped location");
-      final String dataCenterId = location.getId();
+      checkArgument(template instanceof TemplateWithDataCenter, "This implementation requires a TemplateWithDataCenter");
+      return createNodeWithGroupEncodedIntoName(group, name, TemplateWithDataCenter.class.cast(template));
+   }
+
+   protected NodeAndInitialCredentials<Server> createNodeWithGroupEncodedIntoName(String group, String name, TemplateWithDataCenter template) {
+      checkArgument(template.getLocation().getScope() == LocationScope.ZONE, "Template must use a ZONE-scoped location");
+      final String dataCenterId = template.getDataCenter().id();
 
       Hardware hardware = template.getHardware();
 
@@ -314,29 +318,9 @@ public class ProfitBricksComputeServiceAdapter implements ComputeServiceAdapter<
    }
 
    @Override
-   public Iterable<DataCenter> listLocations() {
-      logger.trace("<< fetching datacenters..");
-      final DataCenterApi dcApi = api.dataCenterApi();
-
-      // Fetch all datacenters
-      ListenableFuture<List<DataCenter>> futures = allAsList(transform(dcApi.getAllDataCenters(),
-              new Function<DataCenter, ListenableFuture<DataCenter>>() {
-
-                 @Override
-                 public ListenableFuture<DataCenter> apply(final DataCenter input) {
-                    // Fetch more details in parallel
-                    return executorService.submit(new Callable<DataCenter>() {
-                       @Override
-                       public DataCenter call() throws Exception {
-                          logger.trace("<< fetching datacenter with id [%s]", input.id());
-                          return dcApi.getDataCenter(input.id());
-                       }
-
-                    });
-                 }
-              }));
-
-      return getUnchecked(futures);
+   public Iterable<Location> listLocations() {
+      // Will never be called
+      throw new UnsupportedOperationException("Locations are configured in jclouds properties");
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksTemplateBuilderImpl.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksTemplateBuilderImpl.java b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksTemplateBuilderImpl.java
deleted file mode 100644
index a1967f8..0000000
--- a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksTemplateBuilderImpl.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.profitbricks.compute;
-
-import static com.google.common.collect.Iterables.find;
-import static java.lang.String.format;
-import static org.jclouds.domain.LocationScope.ZONE;
-
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Provider;
-
-import org.jclouds.collect.Memoized;
-import org.jclouds.compute.domain.Hardware;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.domain.TemplateBuilder;
-import org.jclouds.compute.domain.internal.TemplateBuilderImpl;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.domain.Location;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-
-import org.jclouds.compute.domain.Image;
-
-public class ProfitBricksTemplateBuilderImpl extends TemplateBuilderImpl {
-
-   private final Function<org.jclouds.profitbricks.domain.Location, Location> fnLocation;
-
-   @Inject
-   ProfitBricksTemplateBuilderImpl(@Memoized Supplier<Set<? extends Location>> locations,
-         @Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwares,
-         Supplier<Location> defaultLocation, @Named("DEFAULT") Provider<TemplateOptions> optionsProvider,
-         @Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider,
-         Function<org.jclouds.profitbricks.domain.Location, Location> fnLocation) {
-      super(locations, images, hardwares, defaultLocation, optionsProvider, defaultTemplateProvider);
-      this.fnLocation = fnLocation;
-   }
-
-   @Override
-   public TemplateBuilder locationId(final String locationId) {
-      org.jclouds.profitbricks.domain.Location nativeLocation
-              = org.jclouds.profitbricks.domain.Location.fromId(locationId);
-
-      Set<? extends Location> dataCenters = this.locations.get();
-      if (nativeLocation != org.jclouds.profitbricks.domain.Location.UNRECOGNIZED)
-         try {
-            // look for a child location instead if provided id is a Region
-            final Location parentLocation = fnLocation.apply(nativeLocation);
-            this.location = find(dataCenters, new Predicate<Location>() {
-
-               @Override
-               public boolean apply(Location input) {
-                  return parentLocation.equals(input.getParent());
-               }
-
-               @Override
-               public String toString() {
-                  return "first datacenter in locationId(" + locationId + ")";
-               }
-
-            });
-         } catch (NoSuchElementException ex) {
-            throw new NoSuchElementException(
-                    format("no child location found for location id %s in: %s", locationId, locations));
-         }
-      else
-         super.locationId(locationId);
-      return this;
-   }
-
-   @Override
-   public Template build() {
-      Template template = super.build();
-
-      Location loc = template.getLocation();
-      if (loc != null && loc.getScope() != ZONE)
-         return fromTemplate(template).locationId(loc.getId()).build();
-
-      return template;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/compute/config/ProfitBricksComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/config/ProfitBricksComputeServiceContextModule.java b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/config/ProfitBricksComputeServiceContextModule.java
index 629fadc..abc732d 100644
--- a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/config/ProfitBricksComputeServiceContextModule.java
+++ b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/config/ProfitBricksComputeServiceContextModule.java
@@ -36,8 +36,8 @@ import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.TemplateBuilder;
 import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
 import org.jclouds.domain.Location;
 import org.jclouds.functions.IdentityFunction;
 import org.jclouds.lifecycle.Closer;
@@ -47,50 +47,40 @@ import org.jclouds.profitbricks.ProfitBricksApi;
 import org.jclouds.profitbricks.compute.ProfitBricksComputeServiceAdapter;
 import org.jclouds.profitbricks.compute.concurrent.ProvisioningJob;
 import org.jclouds.profitbricks.compute.concurrent.ProvisioningManager;
-import org.jclouds.profitbricks.domain.DataCenter;
-import org.jclouds.profitbricks.domain.Server;
-import org.jclouds.profitbricks.domain.Storage;
-import org.jclouds.profitbricks.compute.ProfitBricksTemplateBuilderImpl;
-import org.jclouds.profitbricks.compute.function.DataCenterToLocation;
-import org.jclouds.profitbricks.compute.function.LocationToLocation;
 import org.jclouds.profitbricks.compute.function.ProvisionableToImage;
 import org.jclouds.profitbricks.compute.function.ServerToNodeMetadata;
 import org.jclouds.profitbricks.compute.function.StorageToVolume;
-import org.jclouds.profitbricks.domain.ProvisioningState;
+import org.jclouds.profitbricks.compute.strategy.AssignDataCenterToTemplate;
 import org.jclouds.profitbricks.domain.Provisionable;
+import org.jclouds.profitbricks.domain.ProvisioningState;
+import org.jclouds.profitbricks.domain.Server;
+import org.jclouds.profitbricks.domain.Storage;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.inject.Inject;
 import com.google.inject.Provides;
+import com.google.inject.Scopes;
 import com.google.inject.TypeLiteral;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 
 public class ProfitBricksComputeServiceContextModule extends
-        ComputeServiceAdapterContextModule<Server, Hardware, Provisionable, DataCenter> {
+        ComputeServiceAdapterContextModule<Server, Hardware, Provisionable, Location> {
 
+   @SuppressWarnings("unchecked")
    @Override
    protected void configure() {
       super.configure();
 
-      install(new LocationsFromComputeServiceAdapterModule<Server, Hardware, Provisionable, DataCenter>() {
-      });
-
       install(new FactoryModuleBuilder().build(ProvisioningJob.Factory.class));
 
-      bind(ImplicitLocationSupplier.class).to(OnlyLocationOrFirstZone.class).in(Singleton.class);
+      bind(ImplicitLocationSupplier.class).to(OnlyLocationOrFirstZone.class).in(Scopes.SINGLETON);
 
-      bind(new TypeLiteral<TemplateBuilder>(){}).to(ProfitBricksTemplateBuilderImpl.class);
-      
-      bind(new TypeLiteral<ComputeServiceAdapter<Server, Hardware, Provisionable, DataCenter>>() {
-      }).to(ProfitBricksComputeServiceAdapter.class);
+      bind(CreateNodesInGroupThenAddToSet.class).to(AssignDataCenterToTemplate.class).in(Scopes.SINGLETON);
 
-      bind(new TypeLiteral<Function<org.jclouds.profitbricks.domain.Location, Location>>() {
-      }).to(LocationToLocation.class);
-
-      bind(new TypeLiteral<Function<DataCenter, Location>>() {
-      }).to(DataCenterToLocation.class);
+      bind(new TypeLiteral<ComputeServiceAdapter<Server, Hardware, Provisionable, Location>>() {
+      }).to(ProfitBricksComputeServiceAdapter.class);
 
       bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
       }).to(ServerToNodeMetadata.class);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/DataCenterToLocation.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/DataCenterToLocation.java b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/DataCenterToLocation.java
deleted file mode 100644
index 93fb3a0..0000000
--- a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/DataCenterToLocation.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.profitbricks.compute.function;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import org.jclouds.domain.Location;
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
-import org.jclouds.profitbricks.domain.DataCenter;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableMap;
-import com.google.inject.Inject;
-
-public class DataCenterToLocation implements Function<DataCenter, Location> {
-
-   private final Function<org.jclouds.profitbricks.domain.Location, Location> fnRegion;
-
-   @Inject
-   DataCenterToLocation(Function<org.jclouds.profitbricks.domain.Location, Location> fnRegion) {
-      this.fnRegion = fnRegion;
-   }
-
-   @Override
-   public Location apply(DataCenter dataCenter) {
-      checkNotNull(dataCenter, "Null dataCenter");
-
-      LocationBuilder builder = new LocationBuilder()
-              .id(dataCenter.id())
-              .description(dataCenter.name())
-              .scope(LocationScope.ZONE)
-              .metadata(ImmutableMap.<String, Object>of(
-                              "version", dataCenter.version(),
-                              "state", dataCenter.state()));
-      if (dataCenter.location() != null)
-         builder.parent(fnRegion.apply(dataCenter.location()));
-      return builder.build();
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/LocationToLocation.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/LocationToLocation.java b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/LocationToLocation.java
deleted file mode 100644
index 999069b..0000000
--- a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/LocationToLocation.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.profitbricks.compute.function;
-
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
-import org.jclouds.location.suppliers.all.JustProvider;
-import org.jclouds.profitbricks.domain.Location;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-import com.google.inject.Inject;
-
-public class LocationToLocation implements Function<Location, org.jclouds.domain.Location> {
-
-   private final JustProvider justProvider;
-
-   @Inject
-   LocationToLocation(JustProvider justProvider) {
-      this.justProvider = justProvider;
-   }
-
-   @Override
-   public org.jclouds.domain.Location apply(Location in) {
-      return new LocationBuilder()
-              .id(in.getId())
-              .description(in.getDescription())
-              .scope(LocationScope.REGION)
-              .parent(Iterables.getOnlyElement(justProvider.get()))
-              .build();
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ProvisionableToImage.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ProvisionableToImage.java b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ProvisionableToImage.java
index 4d0f511..5b27370 100644
--- a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ProvisionableToImage.java
+++ b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ProvisionableToImage.java
@@ -18,9 +18,13 @@ package org.jclouds.profitbricks.compute.function;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.find;
+import static org.jclouds.location.predicates.LocationPredicates.idEquals;
 
+import java.util.Set;
 import java.util.regex.Pattern;
 
+import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.ImageBuilder;
 import org.jclouds.compute.domain.OperatingSystem;
@@ -33,6 +37,7 @@ import org.jclouds.profitbricks.domain.Provisionable;
 
 import com.google.common.base.Function;
 import com.google.common.base.Strings;
+import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableMap;
 import com.google.inject.Inject;
 
@@ -44,9 +49,9 @@ public class ProvisionableToImage implements Function<Provisionable, Image> {
    private final SnapshotToImage fnSnapshotToImage;
 
    @Inject
-   ProvisionableToImage(Function<org.jclouds.profitbricks.domain.Location, Location> fnRegion) {
-      this.fnImageToImage = new ImageToImage(fnRegion);
-      this.fnSnapshotToImage = new SnapshotToImage(fnRegion);
+   ProvisionableToImage(@Memoized Supplier<Set<? extends Location>> locations) {
+      this.fnImageToImage = new ImageToImage(locations);
+      this.fnSnapshotToImage = new SnapshotToImage(locations);
    }
 
    @Override
@@ -83,16 +88,17 @@ public class ProvisionableToImage implements Function<Provisionable, Image> {
 
       private static final Pattern HAS_NUMBERS = Pattern.compile(".*\\d+.*");
 
-      private final Function<org.jclouds.profitbricks.domain.Location, Location> fnRegion;
+      private final Supplier<Set<? extends Location>> locations;
 
-      ImageToImage(Function<org.jclouds.profitbricks.domain.Location, Location> fnRegion) {
-         this.fnRegion = fnRegion;
+      ImageToImage(Supplier<Set<? extends Location>> locations) {
+         this.locations = locations;
       }
 
       @Override
       public Image apply(org.jclouds.profitbricks.domain.Image from) {
          String desc = from.name();
          OsFamily osFamily = parseOsFamily(desc, from.osType());
+         Location location = find(locations.get(), idEquals(from.location().getId()));
 
          OperatingSystem os = OperatingSystem.builder()
                  .description(osFamily.value())
@@ -104,7 +110,7 @@ public class ProvisionableToImage implements Function<Provisionable, Image> {
          return addTypeMetadata(new ImageBuilder()
                  .ids(from.id())
                  .name(desc)
-                 .location(fnRegion.apply(from.location()))
+                 .location(location)
                  .status(Image.Status.AVAILABLE)
                  .operatingSystem(os))
                  .build();
@@ -159,16 +165,17 @@ public class ProvisionableToImage implements Function<Provisionable, Image> {
 
    private static class SnapshotToImage implements ImageFunction<Snapshot> {
 
-      private final Function<org.jclouds.profitbricks.domain.Location, Location> fnRegion;
+      private final Supplier<Set<? extends Location>> locations;
 
-      SnapshotToImage(Function<org.jclouds.profitbricks.domain.Location, Location> fnRegion) {
-         this.fnRegion = fnRegion;
+      SnapshotToImage(Supplier<Set<? extends Location>> locations) {
+         this.locations = locations;
       }
 
       @Override
       public Image apply(Snapshot from) {
          String textToParse = from.name() + from.description();
          OsFamily osFamily = parseOsFamily(textToParse, from.osType());
+         Location location = find(locations.get(), idEquals(from.location().getId()));
 
          OperatingSystem os = OperatingSystem.builder()
                  .description(osFamily.value())
@@ -181,7 +188,7 @@ public class ProvisionableToImage implements Function<Provisionable, Image> {
                  .ids(from.id())
                  .name(from.name())
                  .description(from.description())
-                 .location(fnRegion.apply(from.location()))
+                 .location(location)
                  .status(mapStatus(from.state()))
                  .operatingSystem(os))
                  .build();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadata.java b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadata.java
index 9a8d551..9831c6f 100644
--- a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadata.java
+++ b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadata.java
@@ -18,18 +18,13 @@ package org.jclouds.profitbricks.compute.function;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Predicates.not;
-import static org.jclouds.profitbricks.domain.OsType.LINUX;
-import static org.jclouds.profitbricks.domain.OsType.WINDOWS;
-import static org.jclouds.profitbricks.domain.Server.Status.BLOCKED;
-import static org.jclouds.profitbricks.domain.Server.Status.CRASHED;
-import static org.jclouds.profitbricks.domain.Server.Status.PAUSED;
-import static org.jclouds.profitbricks.domain.Server.Status.RUNNING;
-import static org.jclouds.profitbricks.domain.Server.Status.SHUTDOWN;
-import static org.jclouds.profitbricks.domain.Server.Status.SHUTOFF;
+import static com.google.common.collect.Iterables.find;
+import static org.jclouds.location.predicates.LocationPredicates.idEquals;
 
 import java.util.List;
 import java.util.Set;
 
+import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.HardwareBuilder;
 import org.jclouds.compute.domain.NodeMetadata;
@@ -38,7 +33,10 @@ import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.domain.OsFamily;
 import org.jclouds.compute.domain.Processor;
 import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.domain.Location;
+import org.jclouds.profitbricks.ProfitBricksApi;
+import org.jclouds.profitbricks.domain.DataCenter;
 import org.jclouds.profitbricks.domain.Nic;
 import org.jclouds.profitbricks.domain.OsType;
 import org.jclouds.profitbricks.domain.Server;
@@ -46,32 +44,30 @@ import org.jclouds.profitbricks.domain.Storage;
 import org.jclouds.util.InetAddresses2.IsPrivateIPAddress;
 
 import com.google.common.base.Function;
-import com.google.common.base.Predicate;
 import com.google.common.base.Supplier;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 
-import org.jclouds.collect.Memoized;
-import org.jclouds.compute.functions.GroupNamingConvention;
-
 public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
 
    private final Function<Storage, Volume> fnVolume;
-   private final Supplier<Set<? extends Location>> locationSupply;
+   private final Supplier<Set<? extends Location>> locations;
    private final Function<List<Nic>, List<String>> fnCollectIps;
+   private final ProfitBricksApi api;
 
    private final GroupNamingConvention groupNamingConvention;
 
    @Inject
    ServerToNodeMetadata(Function<Storage, Volume> fnVolume,
-           @Memoized Supplier<Set<? extends Location>> locationsSupply,
+           @Memoized Supplier<Set<? extends Location>> locations,
+           ProfitBricksApi api,
            GroupNamingConvention.Factory groupNamingConvention) {
       this.fnVolume = fnVolume;
-      this.locationSupply = locationsSupply;
+      this.locations = locations;
+      this.api = api;
       this.groupNamingConvention = groupNamingConvention.createWithoutPrefix();
       this.fnCollectIps = new Function<List<Nic>, List<String>>() {
-
          @Override
          public List<String> apply(List<Nic> in) {
             List<String> ips = Lists.newArrayListWithExpectedSize(in.size());
@@ -85,17 +81,9 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
    @Override
    public NodeMetadata apply(final Server server) {
       checkNotNull(server, "Null server");
-
-      // Map fetched dataCenterId with actual populated object
-      Location location = null;
-      if (server.dataCenter() != null)
-         location = Iterables.find(locationSupply.get(), new Predicate<Location>() {
-
-            @Override
-            public boolean apply(Location t) {
-               return t.getId().equals(server.dataCenter().id());
-            }
-         });
+      // Location is not populated in the datacenter on a server response
+      DataCenter dataCenter = api.dataCenterApi().getDataCenter(server.dataCenter().id());
+      Location location = find(locations.get(), idEquals(dataCenter.location().getId()));
 
       float size = 0f;
       List<Volume> volumes = Lists.newArrayList();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/compute/strategy/AssignDataCenterToTemplate.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/strategy/AssignDataCenterToTemplate.java b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/strategy/AssignDataCenterToTemplate.java
new file mode 100644
index 0000000..f7db219
--- /dev/null
+++ b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/strategy/AssignDataCenterToTemplate.java
@@ -0,0 +1,110 @@
+/*
+ * 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.jclouds.profitbricks.compute.strategy;
+
+import static com.google.common.collect.Iterables.find;
+import static org.jclouds.Constants.PROPERTY_USER_THREADS;
+import static org.jclouds.profitbricks.config.ProfitBricksComputeProperties.POLL_PREDICATE_DATACENTER;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.config.CustomizationResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
+import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
+import org.jclouds.logging.Logger;
+import org.jclouds.profitbricks.ProfitBricksApi;
+import org.jclouds.profitbricks.domain.DataCenter;
+import org.jclouds.profitbricks.domain.Location;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+/**
+ * Attempts to find a valid datacenter in the configured location where the
+ * servers will be deployed. If no datacenter is found, one will be created.
+ */
+@Beta
+@Singleton
+public class AssignDataCenterToTemplate extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final ProfitBricksApi api;
+   private final Predicate<String> waitDcUntilAvailable;
+
+   @Inject
+   protected AssignDataCenterToTemplate(
+         CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
+         ListNodesStrategy listNodesStrategy,
+         GroupNamingConvention.Factory namingConvention,
+         @Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+         CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
+         ProfitBricksApi api, @Named(POLL_PREDICATE_DATACENTER) Predicate<String> waitDcUntilAvailable) {
+      super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
+            customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
+      this.api = api;
+      this.waitDcUntilAvailable = waitDcUntilAvailable;
+   }
+
+   @Override
+   public Map<?, ListenableFuture<Void>> execute(String group, int count, final Template template,
+         Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
+         Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
+
+      logger.info(">> looking for a datacenter in %s", template.getLocation().getId());
+
+      // Try to find an existing datacenter in the selected location
+      DataCenter dataCenter = find(api.dataCenterApi().getAllDataCenters(), new Predicate<DataCenter>() {
+         @Override
+         public boolean apply(DataCenter input) {
+            // The location field is not populated when getting the list of datacenters
+            DataCenter details = api.dataCenterApi().getDataCenter(input.id());
+            return details != null && template.getLocation().getId().equals(details.location().getId());
+         }
+      }, null);
+
+      if (dataCenter == null) {
+         String name = namingConvention.create().sharedNameForGroup(group);
+         logger.info(">> no datacenter was found. Creating a new one named %s in %s...", name, template.getLocation()
+               .getId());
+         dataCenter = api.dataCenterApi().createDataCenter(
+               DataCenter.Request.creatingPayload(name, Location.fromId(template.getLocation().getId())));
+         waitDcUntilAvailable.apply(dataCenter.id());
+      }
+
+      return super.execute(group, count, new TemplateWithDataCenter(template, dataCenter), goodNodes, badNodes,
+            customizationResponses);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/main/java/org/jclouds/profitbricks/compute/strategy/TemplateWithDataCenter.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/main/java/org/jclouds/profitbricks/compute/strategy/TemplateWithDataCenter.java b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/strategy/TemplateWithDataCenter.java
new file mode 100644
index 0000000..dd689d5
--- /dev/null
+++ b/profitbricks/src/main/java/org/jclouds/profitbricks/compute/strategy/TemplateWithDataCenter.java
@@ -0,0 +1,107 @@
+/*
+ * 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.jclouds.profitbricks.compute.strategy;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.Location;
+import org.jclouds.profitbricks.domain.DataCenter;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Extends the default {@link Template} object to provide the {@link DataCenter}
+ * where the nodes must be created.
+ */
+@Beta
+public class TemplateWithDataCenter implements Template {
+
+   private final Template delegate;
+
+   private final DataCenter dataCenter;
+
+   // For internal use only
+   TemplateWithDataCenter(Template delegate, DataCenter dataCenter) {
+      this.delegate = checkNotNull(delegate, "delegate cannot be null");
+      this.dataCenter = checkNotNull(dataCenter, "dataCenter cannot be null");
+   }
+
+   public DataCenter getDataCenter() {
+      return dataCenter;
+   }
+
+   public Template clone() {
+      return new TemplateWithDataCenter(delegate.clone(), dataCenter);
+   }
+
+   public Hardware getHardware() {
+      return delegate.getHardware();
+   }
+
+   public Image getImage() {
+      return delegate.getImage();
+   }
+
+   public Location getLocation() {
+      return delegate.getLocation();
+   }
+
+   public TemplateOptions getOptions() {
+      return delegate.getOptions();
+   }
+
+   @Override
+   public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((dataCenter == null) ? 0 : dataCenter.hashCode());
+      result = prime * result + ((delegate == null) ? 0 : delegate.hashCode());
+      return result;
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      TemplateWithDataCenter other = (TemplateWithDataCenter) obj;
+      if (dataCenter == null) {
+         if (other.dataCenter != null)
+            return false;
+      } else if (!dataCenter.equals(other.dataCenter))
+         return false;
+      if (delegate == null) {
+         if (other.delegate != null)
+            return false;
+      } else if (!delegate.equals(other.delegate))
+         return false;
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return delegate.toString();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/test/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceLiveTest.java b/profitbricks/src/test/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceLiveTest.java
index dcb1edc..0061090 100644
--- a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceLiveTest.java
+++ b/profitbricks/src/test/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceLiveTest.java
@@ -16,94 +16,25 @@
  */
 package org.jclouds.profitbricks.compute;
 
-import static org.jclouds.profitbricks.BaseProfitBricksLiveTest.testLocation;
-import static org.jclouds.profitbricks.config.ProfitBricksComputeProperties.POLL_PREDICATE_DATACENTER;
-
-import java.util.Objects;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.collect.FluentIterable;
-
+import org.jclouds.compute.domain.ExecResponse;
 import org.jclouds.compute.domain.NodeMetadata;
-import org.testng.annotations.Test;
-
 import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
+import org.jclouds.logging.config.LoggingModule;
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
 import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
-import com.google.inject.Key;
 import com.google.inject.Module;
-import com.google.inject.TypeLiteral;
-import com.google.inject.name.Names;
-
-import org.jclouds.compute.domain.ExecResponse;
-import org.jclouds.logging.config.LoggingModule;
-import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
-import org.jclouds.profitbricks.ProfitBricksApi;
-import org.jclouds.profitbricks.domain.DataCenter;
-import org.jclouds.profitbricks.features.DataCenterApi;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
 
 @Test(groups = "live", singleThreaded = true, testName = "ProfitBricksComputeServiceLiveTest")
 public class ProfitBricksComputeServiceLiveTest extends BaseComputeServiceLiveTest {
 
-   private static final String TEST_DC_NAME = "computeServiceLiveTest-" + System.currentTimeMillis();
-
-   private DataCenter dataCenter;
-
    public ProfitBricksComputeServiceLiveTest() {
       provider = "profitbricks";
    }
 
-   @BeforeClass
-   @Override
-   public void setupContext() {
-      super.setupContext();
-
-      final DataCenterApi api = getDataCenterApi();
-      final Predicate<String> predicate = getDataCenterPredicate();
-      dataCenter = FluentIterable.from(api.getAllDataCenters()).firstMatch(new Predicate<DataCenter>() {
-
-         @Override
-         public boolean apply(DataCenter input) {
-            boolean match = Objects.equals(input.name(), TEST_DC_NAME);
-            if (match && input.location() == testLocation)
-               return predicate.apply(input.id());
-            return match;
-         }
-      }).or(new Supplier<DataCenter>() {
-
-         @Override
-         public DataCenter get() {
-            DataCenter dataCenter = api.createDataCenter(
-                    DataCenter.Request.creatingPayload(TEST_DC_NAME, testLocation));
-            predicate.apply(dataCenter.id());
-
-            return api.getDataCenter(dataCenter.id());
-         }
-      });
-   }
-
-   @AfterClass(groups = {"integration", "live"}, alwaysRun = true)
-   @Override
-   protected void tearDownContext() {
-      super.tearDownContext();
-      if (dataCenter != null)
-         getDataCenterApi().deleteDataCenter(dataCenter.id());
-   }
-
-   private Predicate<String> getDataCenterPredicate() {
-      return client.getContext().utils().injector().getInstance(Key.get(new TypeLiteral<Predicate<String>>() {
-      }, Names.named(POLL_PREDICATE_DATACENTER)));
-   }
-
-   private DataCenterApi getDataCenterApi() {
-      return client.getContext().unwrapApi(ProfitBricksApi.class).dataCenterApi();
-   }
-
    @Override
    protected Module getSshModule() {
       return new SshjSshClientModule();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/DataCenterToLocationTest.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/DataCenterToLocationTest.java b/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/DataCenterToLocationTest.java
deleted file mode 100644
index 7dcf69c..0000000
--- a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/DataCenterToLocationTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.profitbricks.compute.function;
-
-import static org.testng.Assert.assertEquals;
-
-import java.net.URI;
-
-import org.jclouds.domain.Location;
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
-import org.jclouds.location.suppliers.all.JustProvider;
-import org.jclouds.profitbricks.ProfitBricksProviderMetadata;
-import org.jclouds.profitbricks.domain.DataCenter;
-import org.jclouds.profitbricks.domain.ProvisioningState;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
-@Test(groups = "unit", testName = "DataCenterToLocationTest")
-public class DataCenterToLocationTest {
-
-   private DataCenterToLocation fnLocation;
-   private LocationToLocation fnRegion;
-
-   @BeforeTest
-   public void setup() {
-      ProfitBricksProviderMetadata metadata = new ProfitBricksProviderMetadata();
-      JustProvider justProvider = new JustProvider(metadata.getId(), Suppliers.<URI>ofInstance(
-              URI.create(metadata.getEndpoint())), ImmutableSet.<String>of());
-      this.fnRegion = new LocationToLocation(justProvider);
-      this.fnLocation = new DataCenterToLocation(fnRegion);
-   }
-
-   @Test
-   public void testDataCenterToLocation() {
-      DataCenter dataCenter = DataCenter.builder()
-              .id("12345678-abcd-efgh-ijkl-987654321000")
-              .version(10)
-              .name("JClouds-DC")
-              .state(ProvisioningState.AVAILABLE)
-              .location(org.jclouds.profitbricks.domain.Location.DE_FRA)
-              .build();
-
-      Location actual = fnLocation.apply(dataCenter);
-
-      Location expected = new LocationBuilder()
-              .id(dataCenter.id())
-              .description(dataCenter.name())
-              .scope(LocationScope.ZONE)
-              .metadata(ImmutableMap.<String, Object>of(
-                              "version", dataCenter.version(),
-                              "state", dataCenter.state()))
-              .parent(fnRegion.apply(org.jclouds.profitbricks.domain.Location.DE_FRA))
-              .build();
-
-      assertEquals(actual, expected);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/LocationToLocationTest.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/LocationToLocationTest.java b/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/LocationToLocationTest.java
deleted file mode 100644
index 3967cf5..0000000
--- a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/LocationToLocationTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.profitbricks.compute.function;
-
-import static org.testng.Assert.assertEquals;
-
-import java.net.URI;
-
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
-import org.jclouds.location.suppliers.all.JustProvider;
-import org.jclouds.profitbricks.ProfitBricksProviderMetadata;
-import org.jclouds.profitbricks.domain.Location;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-@Test(groups = "unit", testName = "LocationToLocationTest")
-public class LocationToLocationTest {
-
-   private LocationToLocation fnRegion;
-   private JustProvider justProvider;
-
-   @BeforeTest
-   public void setup() {
-      ProfitBricksProviderMetadata metadata = new ProfitBricksProviderMetadata();
-      this.justProvider = new JustProvider(metadata.getId(), Suppliers.<URI>ofInstance(
-              URI.create(metadata.getEndpoint())), ImmutableSet.<String>of());
-      this.fnRegion = new LocationToLocation(justProvider);
-   }
-
-   @Test
-   public void testLocationToLocation() {
-      Location[] locations = Location.values();
-      for (Location loc : locations) {
-         org.jclouds.domain.Location actual = fnRegion.apply(loc);
-         org.jclouds.domain.Location expected = new LocationBuilder()
-                 .id(loc.getId()).description(loc.getDescription()).scope(LocationScope.REGION)
-                 .parent(Iterables.getOnlyElement(justProvider.get())).build();
-
-         assertEquals(actual, expected);
-      }
-
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ProvisionableToImageTest.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ProvisionableToImageTest.java b/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ProvisionableToImageTest.java
index f27b302..ddecc83 100644
--- a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ProvisionableToImageTest.java
+++ b/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ProvisionableToImageTest.java
@@ -16,18 +16,20 @@
  */
 package org.jclouds.profitbricks.compute.function;
 
+import static org.jclouds.profitbricks.domain.Location.US_LAS;
 import static org.testng.Assert.assertEquals;
 
-import java.net.URI;
+import java.util.Calendar;
 import java.util.Date;
+import java.util.Set;
 
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.ImageBuilder;
 import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.location.suppliers.all.JustProvider;
-import org.jclouds.profitbricks.ProfitBricksProviderMetadata;
-import org.jclouds.profitbricks.domain.Location;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
 import org.jclouds.profitbricks.domain.OsType;
 import org.jclouds.profitbricks.domain.ProvisioningState;
 import org.jclouds.profitbricks.domain.Snapshot;
@@ -42,15 +44,13 @@ import com.google.common.collect.ImmutableSet;
 public class ProvisionableToImageTest {
 
    private ProvisionableToImage fnImage;
-   private LocationToLocation fnRegion;
+   
+   private final Location location = new LocationBuilder().id("us/las").description("us/las").scope(LocationScope.ZONE)
+         .parent(new LocationBuilder().id("us").description("us").scope(LocationScope.REGION).build()).build();
 
    @BeforeTest
    public void setup() {
-      ProfitBricksProviderMetadata metadata = new ProfitBricksProviderMetadata();
-      JustProvider justProvider = new JustProvider(metadata.getId(), Suppliers.<URI>ofInstance(
-              URI.create(metadata.getEndpoint())), ImmutableSet.<String>of());
-      this.fnRegion = new LocationToLocation(justProvider);
-      this.fnImage = new ProvisionableToImage(fnRegion);
+      this.fnImage = new ProvisionableToImage(Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet.of(location)));
    }
 
    @Test
@@ -66,7 +66,7 @@ public class ProvisionableToImageTest {
               .name("Ubuntu-14.04-LTS-server-2015-01-01")
               .size(2048f)
               .type(org.jclouds.profitbricks.domain.Image.Type.HDD)
-              .location(Location.US_LAS)
+              .location(US_LAS)
               .isNicHotPlug(true)
               .isNicHotUnPlug(true)
               .osType(OsType.LINUX)
@@ -81,7 +81,7 @@ public class ProvisionableToImageTest {
       Image expected = new ImageBuilder()
               .ids(image.id())
               .name(image.name())
-              .location(fnRegion.apply(Location.US_LAS))
+              .location(location)
               .status(Image.Status.AVAILABLE)
               .operatingSystem(OperatingSystem.builder()
                       .description("UBUNTU")
@@ -103,7 +103,7 @@ public class ProvisionableToImageTest {
               .name("Fedora-19-server-2015-01-01")
               .size(2048f)
               .type(org.jclouds.profitbricks.domain.Image.Type.HDD)
-              .location(Location.DE_FRA)
+              .location(US_LAS)
               .osType(OsType.LINUX)
               .build();
 
@@ -112,7 +112,7 @@ public class ProvisionableToImageTest {
       Image expected1 = new ImageBuilder()
               .ids(image1.id())
               .name(image1.name())
-              .location(fnRegion.apply(image1.location()))
+              .location(location)
               .status(Image.Status.AVAILABLE)
               .operatingSystem(OperatingSystem.builder()
                       .description("FEDORA")
@@ -131,7 +131,7 @@ public class ProvisionableToImageTest {
               .name("clearos-community-6.5.0-x86_64.iso")
               .size(2048f)
               .type(org.jclouds.profitbricks.domain.Image.Type.CDROM)
-              .location(Location.DE_FKB)
+              .location(US_LAS)
               .osType(OsType.LINUX)
               .build();
 
@@ -140,7 +140,7 @@ public class ProvisionableToImageTest {
       Image expected2 = new ImageBuilder()
               .ids(image2.id())
               .name(image2.name())
-              .location(fnRegion.apply(image2.location()))
+              .location(location)
               .status(Image.Status.AVAILABLE)
               .operatingSystem(OperatingSystem.builder()
                       .description("UNRECOGNIZED")
@@ -159,7 +159,7 @@ public class ProvisionableToImageTest {
               .name("windows-2008-r2-server-setup.iso")
               .size(2048f)
               .type(org.jclouds.profitbricks.domain.Image.Type.CDROM)
-              .location(Location.US_LASDEV)
+              .location(US_LAS)
               .osType(OsType.WINDOWS)
               .build();
 
@@ -168,7 +168,7 @@ public class ProvisionableToImageTest {
       Image expected3 = new ImageBuilder()
               .ids(image3.id())
               .name(image3.name())
-              .location(fnRegion.apply(image3.location()))
+              .location(location)
               .status(Image.Status.AVAILABLE)
               .operatingSystem(OperatingSystem.builder()
                       .description("WINDOWS")
@@ -185,6 +185,10 @@ public class ProvisionableToImageTest {
 
    @Test
    public void testSnapshotToImage() {
+      Calendar calendar = Calendar.getInstance();
+      calendar.set(2015, 4, 13);
+      Date date = calendar.getTime();
+      
       Snapshot snapshot1 = Snapshot.builder()
               .isBootable(true)
               .isCpuHotPlug(true)
@@ -195,13 +199,13 @@ public class ProvisionableToImageTest {
               .name("placeholder-snapshot-04/13/2015")
               .description("Created from \"placeholder\" in Data Center \"sbx-computeservice\"")
               .size(2048f)
-              .location(Location.US_LAS)
+              .location(US_LAS)
               .isNicHotPlug(true)
               .isNicHotUnPlug(true)
               .osType(OsType.LINUX)
               .isRamHotPlug(true)
               .isRamHotUnPlug(false)
-              .creationTime(new Date(2015, 4, 13))
+              .creationTime(date)
               .lastModificationTime(new Date())
               .state(ProvisioningState.AVAILABLE)
               .build();
@@ -211,7 +215,7 @@ public class ProvisionableToImageTest {
       Image expected1 = new ImageBuilder()
               .ids(snapshot1.id())
               .name(snapshot1.name())
-              .location(fnRegion.apply(Location.US_LAS))
+              .location(location)
               .status(Image.Status.AVAILABLE)
               .operatingSystem(OperatingSystem.builder()
                       .description(snapshot1.description())
@@ -233,13 +237,13 @@ public class ProvisionableToImageTest {
               .name("jclouds-ubuntu14.10-template")
               .description("Created from \"jclouds-ubuntu14.10 Storage\" in Data Center \"jclouds-computeservice\"")
               .size(10240f)
-              .location(Location.DE_FKB)
+              .location(US_LAS)
               .isNicHotPlug(true)
               .isNicHotUnPlug(true)
               .osType(OsType.LINUX)
               .isRamHotPlug(true)
               .isRamHotUnPlug(false)
-              .creationTime(new Date(2015, 4, 13))
+              .creationTime(date)
               .lastModificationTime(new Date())
               .state(ProvisioningState.INPROCESS)
               .build();
@@ -249,7 +253,7 @@ public class ProvisionableToImageTest {
       Image expected2 = new ImageBuilder()
               .ids(snapshot2.id())
               .name(snapshot2.name())
-              .location(fnRegion.apply(Location.DE_FKB))
+              .location(location)
               .status(Image.Status.PENDING)
               .operatingSystem(OperatingSystem.builder()
                       .description("ubuntu")

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/7b8adc62/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadataTest.java
----------------------------------------------------------------------
diff --git a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadataTest.java b/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadataTest.java
index 7f1da39..60f43ec 100644
--- a/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadataTest.java
+++ b/profitbricks/src/test/java/org/jclouds/profitbricks/compute/function/ServerToNodeMetadataTest.java
@@ -16,11 +16,16 @@
  */
 package org.jclouds.profitbricks.compute.function;
 
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.jclouds.profitbricks.domain.Location.DE_FRA;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
 import java.util.Set;
 
+import org.easymock.EasyMock;
 import org.jclouds.compute.domain.HardwareBuilder;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.NodeMetadataBuilder;
@@ -33,6 +38,7 @@ import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.domain.Location;
 import org.jclouds.domain.LocationBuilder;
 import org.jclouds.domain.LocationScope;
+import org.jclouds.profitbricks.ProfitBricksApi;
 import org.jclouds.profitbricks.ProfitBricksApiMetadata;
 import org.jclouds.profitbricks.domain.AvailabilityZone;
 import org.jclouds.profitbricks.domain.DataCenter;
@@ -41,12 +47,13 @@ import org.jclouds.profitbricks.domain.OsType;
 import org.jclouds.profitbricks.domain.ProvisioningState;
 import org.jclouds.profitbricks.domain.Server;
 import org.jclouds.profitbricks.domain.Storage;
-import org.testng.annotations.BeforeTest;
+import org.jclouds.profitbricks.features.DataCenterApi;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
@@ -56,25 +63,25 @@ import com.google.inject.name.Names;
 public class ServerToNodeMetadataTest {
 
    private ServerToNodeMetadata fnNodeMetadata;
+   
+   private ProfitBricksApi api;
+   
+   private DataCenterApi dataCenterApi;
 
-   @BeforeTest
+   @BeforeMethod
    public void setup() {
       Supplier<Set<? extends Location>> locationsSupply = new Supplier<Set<? extends Location>>() {
-
          @Override
          public Set<? extends Location> get() {
             return ImmutableSet.of(
                     new LocationBuilder()
-                    .id("12345678-abcd-efgh-ijkl-987654321000")
-                    .description("JClouds-DC")
-                    .scope(LocationScope.REGION)
-                    .metadata(ImmutableMap.<String, Object>of(
-                                    "version", "10",
-                                    "state", "AVAILABLE"))
+                    .id("de/fra")
+                    .description("de/fra")
+                    .scope(LocationScope.ZONE)
                     .parent(new LocationBuilder()
-                            .id("de/fra")
-                            .description("Germany, Frankfurt (M)")
-                            .scope(LocationScope.PROVIDER)
+                            .id("de")
+                            .description("de")
+                            .scope(LocationScope.REGION)
                             .build())
                     .build());
          }
@@ -86,15 +93,31 @@ public class ServerToNodeMetadataTest {
             Names.bindProperties(binder(), new ProfitBricksApiMetadata().getDefaultProperties());
          }
       }).getInstance(GroupNamingConvention.Factory.class);
+      
+      dataCenterApi = EasyMock.createMock(DataCenterApi.class);
+      api = EasyMock.createMock(ProfitBricksApi.class);
+
+      expect(dataCenterApi.getDataCenter("mock")).andReturn(
+            DataCenter.builder().id("mock").version(10).location(DE_FRA).build());
+      expect(api.dataCenterApi()).andReturn(dataCenterApi);
+      
+      replay(dataCenterApi, api);
 
-      this.fnNodeMetadata = new ServerToNodeMetadata(new StorageToVolume(), locationsSupply, namingConvention);
+      this.fnNodeMetadata = new ServerToNodeMetadata(new StorageToVolume(), locationsSupply, api, namingConvention);
+   }
+   
+   @AfterMethod
+   public void tearDown() {
+      verify(api, dataCenterApi);
    }
 
    @Test
    public void testServerToNodeMetadata() {
       Server server = Server.builder()
               .dataCenter(DataCenter.builder()
-                      .id("12345678-abcd-efgh-ijkl-987654321000").version(10)
+                      .id("mock")
+                      .version(10)
+                      .location(org.jclouds.profitbricks.domain.Location.DE_FRA)
                       .build())
               .id("qwertyui-qwer-qwer-qwer-qwertyyuiiop")
               .name("mock-facebook-node")
@@ -164,16 +187,13 @@ public class ServerToNodeMetadataTest {
                       .family(OsFamily.LINUX)
                       .build())
               .location(new LocationBuilder()
-                      .id("12345678-abcd-efgh-ijkl-987654321000")
-                      .description("JClouds-DC")
-                      .scope(LocationScope.REGION)
-                      .metadata(ImmutableMap.<String, Object>of(
-                                      "version", "10",
-                                      "state", "AVAILABLE"))
+                      .id("de/fra")
+                      .description("de/fra")
+                      .scope(LocationScope.ZONE)
                       .parent(new LocationBuilder()
-                              .id("de/fra")
-                              .description("Germany, Frankfurt (M)")
-                              .scope(LocationScope.PROVIDER)
+                              .id("de")
+                              .description("de")
+                              .scope(LocationScope.REGION)
                               .build())
                       .build())
               .publicAddresses(ImmutableList.<String>of("173.252.120.6"))