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/10/06 11:09:46 UTC

[3/4] jclouds-labs git commit: ComputeService implementation for ProfitBricks Rest

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/strategy/AssignDataCenterToTemplate.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/strategy/AssignDataCenterToTemplate.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/strategy/AssignDataCenterToTemplate.java
new file mode 100644
index 0000000..445f6c9
--- /dev/null
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/strategy/AssignDataCenterToTemplate.java
@@ -0,0 +1,100 @@
+/*
+ * 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.jclouds.profitbricks.rest.compute.strategy;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Predicate;
+import static com.google.common.collect.Iterables.find;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+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.apache.jclouds.profitbricks.rest.ProfitBricksApi;
+import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_PREDICATE_DATACENTER;
+import org.apache.jclouds.profitbricks.rest.domain.DataCenter;
+import static org.jclouds.Constants.PROPERTY_USER_THREADS;
+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;
+
+@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().list(), 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.properties().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().create(name, "desc,,,", 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/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/strategy/TemplateWithDataCenter.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/strategy/TemplateWithDataCenter.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/strategy/TemplateWithDataCenter.java
new file mode 100644
index 0000000..71c7522
--- /dev/null
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/strategy/TemplateWithDataCenter.java
@@ -0,0 +1,108 @@
+/*
+ * 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.jclouds.profitbricks.rest.compute.strategy;
+
+import com.google.common.annotations.Beta;
+import static com.google.common.base.Preconditions.checkNotNull;
+import org.apache.jclouds.profitbricks.rest.domain.DataCenter;
+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;
+
+@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/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/config/ProfitBricksComputeProperties.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/config/ProfitBricksComputeProperties.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/config/ProfitBricksComputeProperties.java
index b05a8b8..1835a84 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/config/ProfitBricksComputeProperties.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/config/ProfitBricksComputeProperties.java
@@ -18,15 +18,14 @@ package org.apache.jclouds.profitbricks.rest.config;
 
 public class ProfitBricksComputeProperties {
 
+   public static final String POLL_PREDICATE_SERVER = "jclouds.profitbricks.rest.predicate.server";
    public static final String POLL_PREDICATE_DATACENTER = "jclouds.profitbricks.rest.predicate.datacenter";
    public static final String POLL_PREDICATE_SNAPSHOT = "jclouds.profitbricks.rest.predicate.snapshot";
+   public static final String POLL_PREDICATE_NIC = "jclouds.profitbricks.rest.predicate.nic";
 
    public static final String POLL_TIMEOUT = "jclouds.profitbricks.rest.poll.timeout";
    public static final String POLL_PERIOD = "jclouds.profitbricks.rest.operation.poll.initial-period";
    public static final String POLL_MAX_PERIOD = "jclouds.profitbricks.rest.operation.poll.max-period";
-   
-   public static final String TIMEOUT_NODE_RUNNING = "jclouds.profitbricks.rest.operation.poll.node.running";
-   public static final String TIMEOUT_NODE_SUSPENDED = "jclouds.profitbricks.rest.operation.poll.node.suspended";
 
    private ProfitBricksComputeProperties() {
       throw new AssertionError("Intentionally unimplemented");

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/CpuFamily.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/CpuFamily.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/CpuFamily.java
new file mode 100644
index 0000000..9de0302
--- /dev/null
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/CpuFamily.java
@@ -0,0 +1,28 @@
+/*
+ * 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.jclouds.profitbricks.rest.domain;
+
+import com.google.common.base.Enums;
+
+public enum CpuFamily {
+
+   AMD_OPTERON, INTEL_XEON, UNRECOGNIZED;
+
+   public static CpuFamily fromValue(String v) {
+      return Enums.getIfPresent(CpuFamily.class, v).or(UNRECOGNIZED);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/DataCenter.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/DataCenter.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/DataCenter.java
index 8f3bd59..b08c0aa 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/DataCenter.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/DataCenter.java
@@ -29,8 +29,10 @@ public abstract class DataCenter {
 
    public abstract String href();
 
+   @Nullable
    public abstract Metadata metadata();
 
+   @Nullable
    public abstract Properties properties();
 
    @Nullable

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Firewall.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Firewall.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Firewall.java
index 6cc91a2..3ad40a7 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Firewall.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Firewall.java
@@ -16,13 +16,11 @@
  */
 package org.apache.jclouds.profitbricks.rest.domain;
 
-import java.util.List;
-
-import org.jclouds.javax.annotation.Nullable;
-
 import com.google.auto.value.AutoValue;
 import com.google.common.base.Enums;
 import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.jclouds.javax.annotation.Nullable;
 
 @AutoValue
 public abstract class Firewall {
@@ -46,7 +44,7 @@ public abstract class Firewall {
    public abstract Boolean active();
 
    @Nullable
-   public abstract ProvisioningState state();
+   public abstract State state();
 
    @Nullable
    public abstract List<Rule> rules();
@@ -67,15 +65,15 @@ public abstract class Firewall {
 
       public abstract Builder active(Boolean active);
 
-      public abstract Builder state(ProvisioningState state);
+      public abstract Builder state(State state);
 
       public abstract Builder rules(List<Rule> rules);
 
       abstract Firewall autoBuild();
-      
-      public Firewall build(){
+
+      public Firewall build() {
          Firewall built = autoBuild();
-         
+
          return built.toBuilder()
                  .rules(ImmutableList.copyOf(built.rules()))
                  .autoBuild();

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Image.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Image.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Image.java
index 7adf364..f1135be 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Image.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Image.java
@@ -22,82 +22,91 @@ import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
 @AutoValue
-public abstract class Image {
+public abstract class Image implements Provisionable {
 
-    public abstract String id();
+   public enum Type {
 
-    public abstract String type();
+      HDD, CDROM, UNRECOGNIZED;
 
-    public abstract String href();
+      public static Type fromValue(String v) {
+         return Enums.getIfPresent(Type.class, v).or(UNRECOGNIZED);
+      }
+   }
 
-    @Nullable
-    public abstract Metadata metadata();
+   public abstract String id();
 
-    @Nullable
-    public abstract Properties properties();
+   public abstract String type();
 
-    @SerializedNames({"id", "type", "href", "metadata", "properties"})
-    public static Image create(String id, String type, String href, Metadata metadata, Properties properties) {
-        return new AutoValue_Image(id, type, href, metadata, properties);
-    }
+   public abstract String href();
 
-    @AutoValue
-    public abstract static class Properties {
+   @Nullable
+   public abstract Metadata metadata();
 
-        public enum BusType {
+   @Nullable
+   public abstract Properties properties();
 
-            IDE, SCSI, VIRTIO, UNRECOGNIZED;
+   @SerializedNames({"id", "type", "href", "metadata", "properties"})
+   public static Image create(String id, String type, String href, Metadata metadata, Properties properties) {
+      return new AutoValue_Image(id, type, href, metadata, properties);
+   }
 
-            public static BusType fromValue(String value) {
-                return Enums.getIfPresent(BusType.class, value).or(UNRECOGNIZED);
-            }
-        }
+   @AutoValue
+   public abstract static class Properties {
+
+      public enum BusType {
 
-        public abstract String name();
+         IDE, SCSI, VIRTIO, UNRECOGNIZED;
 
-        @Nullable
-        public abstract String description();
-        
-        public abstract Location location();
+         public static BusType fromValue(String value) {
+            return Enums.getIfPresent(BusType.class, value).or(UNRECOGNIZED);
+         }
+      }
 
-        public abstract float size();
-        
-        public abstract boolean isPublic();
-        
-        public abstract LicenceType licenceType();
+      public abstract String name();
 
-        public abstract Image.Type imageType();
+      @Nullable
+      public abstract String description();
 
-        public abstract boolean cpuHotPlug();
+      public abstract Location location();
 
-        public abstract boolean cpuHotUnplug();
+      public abstract float size();
 
-        public abstract boolean ramHotPlug();
+      public abstract boolean isPublic();
 
-        public abstract boolean ramHotUnplug();
+      public abstract LicenceType licenceType();
 
-        public abstract boolean nicHotPlug();
+      public abstract Image.Type imageType();
 
-        public abstract boolean nicHotUnplug();
+      public abstract boolean cpuHotPlug();
 
-        public abstract boolean discVirtioHotPlug();
+      public abstract boolean cpuHotUnplug();
 
-        public abstract boolean discVirtioHotUnplug();
+      public abstract boolean ramHotPlug();
 
-        public abstract boolean discScsiHotPlug();
+      public abstract boolean ramHotUnplug();
 
-        public abstract boolean discScsiHotUnplug();
+      public abstract boolean nicHotPlug();
 
-        @SerializedNames({"name", "description", "location", "size", "public", "licenceType", "imageType", "cpuHotPlug", "cpuHotUnplug", "ramHotPlug", "ramHotUnplug", "nicHotPlug", "nicHotUnplug", "discVirtioHotPlug", "discVirtioHotUnplug", "discScsiHotPlug", "discScsiHotUnplug"})
-        public static Image.Properties create(String name, String description, Location location, float size, boolean isPublic, LicenceType licenceType, Image.Type imageType,
-                boolean cpuHotPlug, boolean cpuHotUnplug, boolean ramHotPlug, boolean ramHotUnplug, boolean nicHotPlug, boolean nicHotUnplug, boolean discVirtioHotPlug,
-                boolean discVirtioHotUnplug, boolean discScsiHotPlug, boolean discScsiHotUnplug) {
+      public abstract boolean nicHotUnplug();
 
-            return new AutoValue_Image_Properties(name, description, location, size, isPublic, licenceType, imageType, cpuHotPlug, cpuHotUnplug, ramHotPlug, ramHotUnplug, nicHotPlug, nicHotUnplug, discVirtioHotPlug, discVirtioHotUnplug, discScsiHotPlug, discScsiHotUnplug);
+      public abstract boolean discVirtioHotPlug();
 
-        }
+      public abstract boolean discVirtioHotUnplug();
+
+      public abstract boolean discScsiHotPlug();
+
+      public abstract boolean discScsiHotUnplug();
+
+      @SerializedNames({"name", "description", "location", "size", "public", "licenceType", "imageType", "cpuHotPlug", "cpuHotUnplug", "ramHotPlug", "ramHotUnplug", "nicHotPlug", "nicHotUnplug", "discVirtioHotPlug", "discVirtioHotUnplug", "discScsiHotPlug", "discScsiHotUnplug"})
+      public static Image.Properties create(String name, String description, Location location, float size, boolean isPublic, LicenceType licenceType, Image.Type imageType,
+              boolean cpuHotPlug, boolean cpuHotUnplug, boolean ramHotPlug, boolean ramHotUnplug, boolean nicHotPlug, boolean nicHotUnplug, boolean discVirtioHotPlug,
+              boolean discVirtioHotUnplug, boolean discScsiHotPlug, boolean discScsiHotUnplug) {
+
+         return new AutoValue_Image_Properties(name, description, location, size, isPublic, licenceType, imageType, cpuHotPlug, cpuHotUnplug, ramHotPlug, ramHotUnplug, nicHotPlug, nicHotUnplug, discVirtioHotPlug, discVirtioHotUnplug, discScsiHotPlug, discScsiHotUnplug);
+
+      }
    }
-    
+
    public static final class Request {
 
       public static UpdatePayload.Builder updatingBuilder() {
@@ -111,7 +120,7 @@ public abstract class Image {
 
          @Nullable
          public abstract String name();
-         
+
          @Nullable
          public abstract String description();
 
@@ -152,20 +161,33 @@ public abstract class Image {
          public abstract static class Builder {
 
             public abstract Builder id(String id);
+
             public abstract Builder name(String name);
+
             public abstract Builder description(String description);
+
             public abstract Builder licenceType(LicenceType licenceType);
+
             public abstract Builder cpuHotPlug(Boolean cpuHotPlug);
+
             public abstract Builder cpuHotUnplug(Boolean cpuHotUnplug);
+
             public abstract Builder ramHotPlug(Boolean ramHotPlug);
+
             public abstract Builder ramHotUnplug(Boolean ramHotUnplug);
+
             public abstract Builder nicHotPlug(Boolean nicHotPlug);
+
             public abstract Builder nicHotUnplug(Boolean nicHotUnplug);
+
             public abstract Builder discVirtioHotPlug(Boolean discVirtioHotPlug);
+
             public abstract Builder discVirtioHotUnplug(Boolean discVirtioHotUnplug);
+
             public abstract Builder discScsiHotPlug(Boolean discScsiHotPlug);
+
             public abstract Builder discScsiHotUnplug(Boolean discScsiHotUnplug);
-            
+
             abstract UpdatePayload autoBuild();
 
             public UpdatePayload build() {
@@ -173,17 +195,6 @@ public abstract class Image {
             }
          }
       }
-      
-   }
- 
-    
-   public enum Type {
-
-      HDD, CDROM, UNRECOGNIZED;
 
-      public static Type fromValue(String v) {
-         return Enums.getIfPresent(Type.class, v).or(UNRECOGNIZED);
-      }
    }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/IpBlock.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/IpBlock.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/IpBlock.java
new file mode 100644
index 0000000..6836477
--- /dev/null
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/IpBlock.java
@@ -0,0 +1,104 @@
+/*
+ * 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.jclouds.profitbricks.rest.domain;
+
+import com.google.auto.value.AutoValue;
+import java.util.List;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class IpBlock {
+
+   public abstract String id();
+
+   public abstract String type();
+
+   public abstract String href();
+
+   @Nullable
+   public abstract Metadata metadata();
+
+   @Nullable
+   public abstract Properties properties();
+
+   @SerializedNames({"id", "type", "href", "metadata", "properties"})
+   public static IpBlock create(String id, String type, String href, Metadata metadata, Properties properties) {
+      return new AutoValue_IpBlock(id, type, href, metadata, properties);
+   }
+
+   @AutoValue
+   public abstract static class Properties {
+
+      public abstract String name();
+
+      @Nullable
+      public abstract List<String> ips();
+
+      public abstract String location();
+
+      public abstract int size();
+
+      @SerializedNames({"name", "ips", "location", "size"})
+      public static Properties create(String name, List<String> ips, String location, int size) {
+         return new AutoValue_IpBlock_Properties(name, ips, location, size);
+      }
+   }
+
+   @AutoValue
+   public abstract static class PropertiesRequest {
+
+      @Nullable
+      public abstract String name();
+
+      public abstract String location();
+
+      public abstract int size();
+
+      @SerializedNames({"name", "location", "size"})
+      public static PropertiesRequest create(String name, String location, int size) {
+         return new AutoValue_IpBlock_PropertiesRequest(name, location, size);
+      }
+   }
+
+   public static final class Request {
+
+      public static CreatePayload.Builder creatingBuilder() {
+         return new AutoValue_IpBlock_Request_CreatePayload.Builder();
+      }
+
+      @AutoValue
+      public abstract static class CreatePayload {
+
+         public abstract PropertiesRequest properties();
+
+         @AutoValue.Builder
+         public abstract static class Builder {
+
+            public abstract Builder properties(PropertiesRequest properties);
+
+            abstract CreatePayload autoBuild();
+
+            public CreatePayload build() {
+               return autoBuild();
+            }
+         }
+
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Location.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Location.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Location.java
index 79ac418..3ce5163 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Location.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Location.java
@@ -17,12 +17,13 @@
 package org.apache.jclouds.profitbricks.rest.domain;
 
 public enum Location {
-   
+
    DE_FKB("de/fkb", "Germany, Karlsruhe"),
    DE_FRA("de/fra", "Germany, Frankfurt (M)"),
    US_LAS("us/las", "USA, Las Vegas"),
    US_LASDEV("us/lasdev", "USA Developer cluster"),
-   UNRECOGNIZED("unrecognized", "Unrecognized location");
+   UNRECOGNIZED("unrecognized", "Unrecognized location"),
+   MOCK("mock", "Mock");
 
    private final String id;
    private final String description;
@@ -31,10 +32,6 @@ public enum Location {
       this.id = id;
       this.description = description;
    }
-   
-   public String value() {
-      return id;
-   }
 
    public String getId() {
       return id;
@@ -49,9 +46,16 @@ public enum Location {
    }
 
    public static Location fromId(String id) {
-      for (Location location : values())
-         if (location.id.equals(id))
+      for (Location location : values()) {
+         if (location.id.equals(id)) {
             return location;
+         }
+      }
       return UNRECOGNIZED;
    }
+
+   @Override
+   public String toString() {
+      return id;
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Provisionable.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Provisionable.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Provisionable.java
index 9e813d2..54aba06 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Provisionable.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Provisionable.java
@@ -16,10 +16,21 @@
  */
 package org.apache.jclouds.profitbricks.rest.domain;
 
+import com.google.common.base.Enums;
+
 /**
- * Marker interface for {@link org.jclouds.profitbricks.domain.Image} and 
+ * Marker interface for {@link org.jclouds.profitbricks.domain.Image} and
  * {@link org.jclouds.profitbricks.domain.Snapshot}
  */
 public interface Provisionable {
 
+   public enum Type {
+
+      IMAGE, SNAPSHOT;
+
+      public static Type fromValue(String v) {
+         return Enums.getIfPresent(Type.class, v).or(IMAGE);
+      }
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Server.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Server.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Server.java
index f574777..833c869 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Server.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Server.java
@@ -24,16 +24,16 @@ import org.jclouds.json.SerializedNames;
 
 @AutoValue
 public abstract class Server {
-   
+
    public abstract String id();
-   
+
    @Nullable
    public abstract String dataCenterId();
 
    public abstract String type();
 
    public abstract String href();
-   
+
    @Nullable
    public abstract Metadata metadata();
 
@@ -59,10 +59,10 @@ public abstract class Server {
 
       @Nullable
       public abstract AvailabilityZone availabilityZone();
-      
+
       @Nullable
       public abstract Server.Status vmState();
-      
+
       @Nullable
       public abstract LicenceType licenceType();
 
@@ -72,9 +72,12 @@ public abstract class Server {
       @Nullable
       public abstract Volume bootCdrom();
 
-      @SerializedNames({"name", "cores", "ram", "availabilityZone", "vmState", "licenceType", "bootVolume", "bootCdrom"})
-      public static Properties create(String name, int cores, int ram, AvailabilityZone availabilityZone, Server.Status vmState, LicenceType licenceType, Volume bootVolume, Volume bootCdrom) {
-         return new AutoValue_Server_Properties(name, cores, ram, availabilityZone, vmState, licenceType, bootVolume, bootCdrom);
+      @Nullable
+      public abstract CpuFamily cpuFamily();
+
+      @SerializedNames({"name", "cores", "ram", "availabilityZone", "vmState", "licenceType", "bootVolume", "bootCdrom", "cpuFamily"})
+      public static Properties create(String name, int cores, int ram, AvailabilityZone availabilityZone, Server.Status vmState, LicenceType licenceType, Volume bootVolume, Volume bootCdrom, CpuFamily cpuFamily) {
+         return new AutoValue_Server_Properties(name, cores, ram, availabilityZone, vmState, licenceType, bootVolume, bootCdrom, cpuFamily);
       }
 
    }
@@ -84,7 +87,7 @@ public abstract class Server {
 
       @Nullable
       public abstract Images cdroms();
-      
+
       @Nullable
       public abstract Volumes volumes();
 
@@ -97,7 +100,19 @@ public abstract class Server {
       }
 
    }
-   
+
+   @AutoValue
+   public abstract static class BootVolume {
+
+      public abstract String id();
+
+      @SerializedNames({"id"})
+      public static BootVolume create(String id) {
+         return new AutoValue_Server_BootVolume(id);
+      }
+
+   }
+
    public static final class Request {
 
       public static CreatePayload.Builder creatingBuilder() {
@@ -107,11 +122,11 @@ public abstract class Server {
       public static UpdatePayload.Builder updatingBuilder() {
          return new AutoValue_Server_Request_UpdatePayload.Builder();
       }
-      
+
       public static AttachCdromPayload.Builder attachCdromBuilder() {
          return new AutoValue_Server_Request_AttachCdromPayload.Builder();
       }
-      
+
       public static AttachVolumePayload.Builder attachVolumeBuilder() {
          return new AutoValue_Server_Request_AttachVolumePayload.Builder();
       }
@@ -120,7 +135,7 @@ public abstract class Server {
       public abstract static class CreatePayload {
 
          public abstract String name();
-         
+
          public abstract int cores();
 
          public abstract int ram();
@@ -128,20 +143,23 @@ public abstract class Server {
          public abstract String dataCenterId();
 
          @Nullable
-         public abstract Volume bootVolume();
+         public abstract BootVolume bootVolume();
 
          @Nullable
-         public abstract Volume bootCdrom();
+         public abstract String bootCdrom();
+
+         @Nullable
+         public abstract CpuFamily cpuFamily();
 
          @Nullable
          public abstract AvailabilityZone availabilityZone();
-         
+
          @Nullable
          public abstract LicenceType licenceType();
-        
+
          @Nullable
          public abstract Entities entities();
-                  
+
          @AutoValue.Builder
          public abstract static class Builder {
 
@@ -153,16 +171,18 @@ public abstract class Server {
 
             public abstract Builder dataCenterId(String dataCenterId);
 
-            public abstract Builder bootVolume(Volume bootVolume);
+            public abstract Builder bootVolume(BootVolume bootVolume);
 
-            public abstract Builder bootCdrom(Volume bootCdrom);
+            public abstract Builder bootCdrom(String bootCdrom);
+
+            public abstract Builder cpuFamily(CpuFamily cpuFamily);
 
             public abstract Builder availabilityZone(AvailabilityZone availabilityZone);
-            
+
             public abstract Builder licenceType(LicenceType licenceType);
-           
+
             public abstract Builder entities(Entities entities);
-            
+
             abstract CreatePayload autoBuild();
 
             public CreatePayload build() {
@@ -178,12 +198,12 @@ public abstract class Server {
       public abstract static class UpdatePayload {
 
          public abstract String id();
-         
+
          public abstract String dataCenterId();
 
          @Nullable
          public abstract String name();
-         
+
          @Nullable
          public abstract Integer cores();
 
@@ -191,14 +211,14 @@ public abstract class Server {
          public abstract Integer ram();
 
          @Nullable
-         public abstract Volume bootVolume();
+         public abstract BootVolume bootVolume();
 
          @Nullable
          public abstract Volume bootCdrom();
 
          @Nullable
          public abstract AvailabilityZone availabilityZone();
-         
+
          @Nullable
          public abstract LicenceType licenceType();
 
@@ -206,46 +226,51 @@ public abstract class Server {
          public abstract static class Builder {
 
             public abstract Builder id(String id);
-            
+
             public abstract Builder dataCenterId(String dataCenterId);
-            
+
             public abstract Builder name(String name);
 
             public abstract Builder cores(Integer cores);
 
             public abstract Builder ram(Integer ram);
 
-            public abstract Builder bootVolume(Volume bootVolume);
+            public abstract Builder bootVolume(BootVolume bootVolume);
 
             public abstract Builder bootCdrom(Volume bootCdrom);
 
             public abstract Builder availabilityZone(AvailabilityZone availabilityZone);
-            
+
             public abstract Builder licenceType(LicenceType licenceType);
 
             abstract UpdatePayload autoBuild();
 
             public UpdatePayload build() {
                UpdatePayload payload = autoBuild();
-               if (payload.cores() != null)
+               if (payload.cores() != null) {
                   checkCores(payload.cores());
+               }
                return payload;
             }
          }
       }
-      
+
       @AutoValue
       public abstract static class AttachCdromPayload {
 
          public abstract String imageId();
+
          public abstract String dataCenterId();
+
          public abstract String serverId();
-         
+
          @AutoValue.Builder
          public abstract static class Builder {
-            
+
             public abstract Builder imageId(String imageId);
+
             public abstract Builder dataCenterId(String dataCenterId);
+
             public abstract Builder serverId(String serverId);
 
             abstract AttachCdromPayload autoBuild();
@@ -255,19 +280,23 @@ public abstract class Server {
             }
          }
       }
-      
-      @AutoValue 
+
+      @AutoValue
       public abstract static class AttachVolumePayload {
 
          public abstract String volumeId();
+
          public abstract String dataCenterId();
+
          public abstract String serverId();
-         
+
          @AutoValue.Builder
          public abstract static class Builder {
-            
+
             public abstract Builder volumeId(String volumeId);
+
             public abstract Builder dataCenterId(String dataCenterId);
+
             public abstract Builder serverId(String serverId);
 
             abstract AttachVolumePayload autoBuild();
@@ -278,7 +307,7 @@ public abstract class Server {
          }
       }
    }
-   
+
    public enum Status {
 
       NOSTATE, RUNNING, BLOCKED, PAUSED, SHUTDOWN, SHUTOFF, CRASHED, UNRECOGNIZED;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Snapshot.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Snapshot.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Snapshot.java
index 2cb3761..5fd1abc 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Snapshot.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/Snapshot.java
@@ -17,11 +17,12 @@
 package org.apache.jclouds.profitbricks.rest.domain;
 
 import com.google.auto.value.AutoValue;
+import java.util.Date;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
 @AutoValue
-public abstract class Snapshot {
+public abstract class Snapshot implements Provisionable {
 
    public abstract String id();
 
@@ -37,57 +38,77 @@ public abstract class Snapshot {
 
    @SerializedNames({"id", "type", "href", "metadata", "properties"})
    public static Snapshot create(String id, String type, String href, Metadata metadata, Properties properties) {
-       return new AutoValue_Snapshot(id, type, href, metadata, properties);
+      return new AutoValue_Snapshot(id, type, href, metadata, properties);
    }
 
    @AutoValue
-   public abstract static class Properties {
+   public abstract static class Metadata {
+
+      public abstract Date createdDate();
+
+      public abstract String createdBy();
+
+      public abstract String etag();
 
-       @Nullable
-       public abstract String name();
+      public abstract Date lastModifiedDate();
 
-       @Nullable
-       public abstract String description();
+      public abstract String lastModifiedBy();
 
-       @Nullable
-       public abstract Integer size();
+      public abstract ProvisioningState state();
 
-       @Nullable
-       public abstract LicenceType licenceType();
+      @SerializedNames({"createdDate", "createdBy", "etag", "lastModifiedDate", "lastModifiedBy", "state"})
+      public static Snapshot.Metadata create(Date createdDate, String createdBy, String etag, Date lastModifiedDate, String lastModifiedBy, ProvisioningState state) {
+         return new AutoValue_Snapshot_Metadata(createdDate, createdBy, etag, lastModifiedDate, lastModifiedBy, state);
+      }
+   }
 
-       public abstract Location location();
+   @AutoValue
+   public abstract static class Properties {
 
-       public abstract boolean cpuHotPlug();
+      @Nullable
+      public abstract String name();
 
-       public abstract boolean cpuHotUnplug();
+      @Nullable
+      public abstract String description();
 
-       public abstract boolean ramHotPlug();
+      @Nullable
+      public abstract Integer size();
 
-       public abstract boolean ramHotUnplug();
+      @Nullable
+      public abstract LicenceType licenceType();
 
-       public abstract boolean nicHotPlug();
+      public abstract Location location();
 
-       public abstract boolean nicHotUnplug();
+      public abstract boolean cpuHotPlug();
 
-       public abstract boolean discVirtioHotPlug();
+      public abstract boolean cpuHotUnplug();
 
-       public abstract boolean discVirtioHotUnplug();
+      public abstract boolean ramHotPlug();
 
-       public abstract boolean discScsiHotPlug();
+      public abstract boolean ramHotUnplug();
 
-       public abstract boolean discScsiHotUnplug();
+      public abstract boolean nicHotPlug();
 
-       @SerializedNames({"name", "description", "size", "licenceType", "location", "cpuHotPlug", "cpuHotUnplug", "ramHotPlug", "ramHotUnplug", "nicHotPlug", "nicHotUnplug", "discVirtioHotPlug", "discVirtioHotUnplug", "discScsiHotPlug", "discScsiHotUnplug"})
-       public static Snapshot.Properties create(String name, String description, Integer size, LicenceType licenceType, Location location,
-               boolean cpuHotPlug, boolean cpuHotUnplug, boolean ramHotPlug, boolean ramHotUnplug, boolean nicHotPlug, boolean nicHotUnplug, boolean discVirtioHotPlug,
-               boolean discVirtioHotUnplug, boolean discScsiHotPlug, boolean discScsiHotUnplug) {
+      public abstract boolean nicHotUnplug();
 
-          return new AutoValue_Snapshot_Properties(name, description, size, licenceType, location, cpuHotPlug, cpuHotUnplug, ramHotPlug, ramHotUnplug, nicHotPlug, nicHotUnplug, discVirtioHotPlug, discVirtioHotUnplug, discScsiHotPlug, discScsiHotUnplug);
+      public abstract boolean discVirtioHotPlug();
 
+      public abstract boolean discVirtioHotUnplug();
 
-       }
+      public abstract boolean discScsiHotPlug();
+
+      public abstract boolean discScsiHotUnplug();
+
+      @SerializedNames({"name", "description", "size", "licenceType", "location", "cpuHotPlug", "cpuHotUnplug", "ramHotPlug", "ramHotUnplug", "nicHotPlug", "nicHotUnplug", "discVirtioHotPlug", "discVirtioHotUnplug", "discScsiHotPlug", "discScsiHotUnplug"})
+      public static Snapshot.Properties create(String name, String description, Integer size, LicenceType licenceType, Location location,
+              boolean cpuHotPlug, boolean cpuHotUnplug, boolean ramHotPlug, boolean ramHotUnplug, boolean nicHotPlug, boolean nicHotUnplug, boolean discVirtioHotPlug,
+              boolean discVirtioHotUnplug, boolean discScsiHotPlug, boolean discScsiHotUnplug) {
+
+         return new AutoValue_Snapshot_Properties(name, description, size, licenceType, location, cpuHotPlug, cpuHotUnplug, ramHotPlug, ramHotUnplug, nicHotPlug, nicHotUnplug, discVirtioHotPlug, discVirtioHotUnplug, discScsiHotPlug, discScsiHotUnplug);
+
+      }
    }
-    
+
    public static final class Request {
 
       public static UpdatePayload.Builder updatingBuilder() {
@@ -101,7 +122,7 @@ public abstract class Snapshot {
 
          @Nullable
          public abstract String name();
-         
+
          @Nullable
          public abstract String description();
 
@@ -142,20 +163,33 @@ public abstract class Snapshot {
          public abstract static class Builder {
 
             public abstract Builder id(String id);
+
             public abstract Builder name(String name);
+
             public abstract Builder description(String description);
+
             public abstract Builder licenceType(LicenceType licenceType);
+
             public abstract Builder cpuHotPlug(Boolean cpuHotPlug);
+
             public abstract Builder cpuHotUnplug(Boolean cpuHotUnplug);
+
             public abstract Builder ramHotPlug(Boolean ramHotPlug);
+
             public abstract Builder ramHotUnplug(Boolean ramHotUnplug);
+
             public abstract Builder nicHotPlug(Boolean nicHotPlug);
+
             public abstract Builder nicHotUnplug(Boolean nicHotUnplug);
+
             public abstract Builder discVirtioHotPlug(Boolean discVirtioHotPlug);
+
             public abstract Builder discVirtioHotUnplug(Boolean discVirtioHotUnplug);
+
             public abstract Builder discScsiHotPlug(Boolean discScsiHotPlug);
+
             public abstract Builder discScsiHotUnplug(Boolean discScsiHotUnplug);
-            
+
             abstract UpdatePayload autoBuild();
 
             public UpdatePayload build() {
@@ -163,8 +197,7 @@ public abstract class Snapshot {
             }
          }
       }
-      
+
    }
 
-    
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/VolumeType.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/VolumeType.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/VolumeType.java
index c4503cd..cdeaa1d 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/VolumeType.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/VolumeType.java
@@ -20,7 +20,7 @@ import com.google.common.base.Enums;
 
 public enum VolumeType {
 
-   HDD, UNRECOGNIZED;
+   HDD, SSD, UNRECOGNIZED;
 
    public static VolumeType fromValue(String v) {
       return Enums.getIfPresent(VolumeType.class, v).or(UNRECOGNIZED);

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/zonescoped/DataCenterAndId.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/zonescoped/DataCenterAndId.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/zonescoped/DataCenterAndId.java
new file mode 100644
index 0000000..c4b1460
--- /dev/null
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/zonescoped/DataCenterAndId.java
@@ -0,0 +1,90 @@
+/*
+ * 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.jclouds.profitbricks.rest.domain.zonescoped;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class DataCenterAndId {
+
+   public static DataCenterAndId fromSlashEncoded(String id) {
+      Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
+      checkArgument(Iterables.size(parts) == 2, "id must be in format dataCenterId/id");
+      return new DataCenterAndId(Iterables.get(parts, 0), Iterables.get(parts, 1));
+   }
+
+   public static DataCenterAndId fromDataCenterAndId(String dataCenterId, String id) {
+      return new DataCenterAndId(dataCenterId, id);
+   }
+
+   private static String slashEncodeDataCenterAndId(String dataCenterId, String id) {
+      return checkNotNull(dataCenterId, "dataCenterId") + "/" + checkNotNull(id, "id");
+   }
+
+   public String slashEncode() {
+      return slashEncodeDataCenterAndId(dataCenterId, id);
+   }
+
+   protected final String dataCenterId;
+   protected final String id;
+
+   protected DataCenterAndId(String dataCenterId, String id) {
+      this.dataCenterId = checkNotNull(dataCenterId, "dataCenterId");
+      this.id = checkNotNull(id, "id");
+   }
+
+   public String getDataCenter() {
+      return dataCenterId;
+   }
+
+   public String getId() {
+      return id;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(dataCenterId, id);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) {
+         return true;
+      }
+      if (obj == null) {
+         return false;
+      }
+      if (getClass() != obj.getClass()) {
+         return false;
+      }
+      DataCenterAndId other = (DataCenterAndId) obj;
+      return Objects.equal(dataCenterId, other.dataCenterId) && Objects.equal(id, other.id);
+   }
+
+   protected Objects.ToStringHelper string() {
+      return Objects.toStringHelper(this).add("dataCenterId", dataCenterId).add("id", id);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/zonescoped/ServerInDataCenter.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/zonescoped/ServerInDataCenter.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/zonescoped/ServerInDataCenter.java
new file mode 100644
index 0000000..7dd862a
--- /dev/null
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/domain/zonescoped/ServerInDataCenter.java
@@ -0,0 +1,46 @@
+/*
+ * 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.jclouds.profitbricks.rest.domain.zonescoped;
+
+import com.google.common.base.Objects;
+import static com.google.common.base.Preconditions.checkNotNull;
+import org.apache.jclouds.profitbricks.rest.domain.Server;
+
+public class ServerInDataCenter extends DataCenterAndId {
+
+   protected final Server server;
+
+   public ServerInDataCenter(Server server, String regionId) {
+      super(regionId, checkNotNull(server, "server").id());
+      this.server = server;
+   }
+
+   public Server getServer() {
+      return server;
+   }
+
+   @Override
+   protected Objects.ToStringHelper string() {
+      return super.string().add("server", server);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/features/IpBlockApi.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/features/IpBlockApi.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/features/IpBlockApi.java
new file mode 100644
index 0000000..d97d981
--- /dev/null
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/features/IpBlockApi.java
@@ -0,0 +1,89 @@
+/*
+ * 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.jclouds.profitbricks.rest.features;
+
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+import java.io.Closeable;
+import java.util.List;
+import javax.inject.Named;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import org.apache.jclouds.profitbricks.rest.domain.IpBlock;
+import org.apache.jclouds.profitbricks.rest.domain.options.DepthOptions;
+import org.apache.jclouds.profitbricks.rest.util.ParseId;
+import org.jclouds.Fallbacks;
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+@Path("/ipblocks")
+@RequestFilters(BasicAuthentication.class)
+public interface IpBlockApi extends Closeable {
+
+   @Named("IpBlock:list")
+   @GET
+   @SelectJson("items")
+   @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+   List<IpBlock> list();
+
+   @Named("IpBlock:list")
+   @GET
+   @SelectJson("items")
+   @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+   List<IpBlock> list(DepthOptions options);
+
+   @Named("IpBlock:get")
+   @GET
+   @Path("/{ipblockId}")
+   @ResponseParser(IpBlockApi.IpBlockParser.class)
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   IpBlock get(@PathParam("ipblockId") String ipblockId);
+
+   @Named("IpBlock:create")
+   @POST
+   @Produces("application/vnd.profitbricks.resource+json")
+   @ResponseParser(IpBlockApi.IpBlockParser.class)
+   IpBlock create(@BinderParam(BindToJsonPayload.class) IpBlock.Request.CreatePayload payload);
+
+   @Named("IpBlock:delete")
+   @DELETE
+   @Path("/{ipblockId}")
+   @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
+   void delete(@PathParam("ipblockId") String ipblockId);
+
+   static final class IpBlockParser extends ParseJson<IpBlock> {
+
+      final ParseId parseService;
+
+      @Inject
+      IpBlockParser(Json json, ParseId parseId) {
+         super(json, TypeLiteral.get(IpBlock.class));
+         this.parseService = parseId;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/features/ServerApi.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/features/ServerApi.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/features/ServerApi.java
index faedf6c..8813497 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/features/ServerApi.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/features/ServerApi.java
@@ -56,7 +56,7 @@ import org.jclouds.util.Strings2;
 @Path("/datacenters/{dataCenterId}/servers")
 @RequestFilters(BasicAuthentication.class)
 public interface ServerApi extends Closeable {
-   
+
    @Named("server:list")
    @GET
    @SelectJson("items")
@@ -68,27 +68,27 @@ public interface ServerApi extends Closeable {
    @SelectJson("items")
    @Fallback(EmptyListOnNotFoundOr404.class)
    List<Server> getList(@PathParam("dataCenterId") String dataCenterId, DepthOptions options);
-   
+
    @Named("server:get")
-   @GET   
+   @GET
    @Path("/{serverId}")
    @ResponseParser(ServerApi.ServerParser.class)
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
    Server getServer(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId);
 
    @Named("server:get")
-   @GET   
+   @GET
    @Path("/{serverId}")
    @ResponseParser(ServerApi.ServerParser.class)
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
    Server getServer(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId, DepthOptions options);
-   
+
    @Named("server:create")
    @POST
    @MapBinder(CreateServerRequestBinder.class)
    @ResponseParser(ServerApi.ServerParser.class)
    Server createServer(@PayloadParam("server") Server.Request.CreatePayload payload);
-   
+
    @Named("server:update")
    @PATCH
    @Path("/{serverId}")
@@ -96,85 +96,86 @@ public interface ServerApi extends Closeable {
    @ResponseParser(ServerApi.ServerParser.class)
    @Produces("application/vnd.profitbricks.partial-properties+json")
    Server updateServer(@PayloadParam("server") Server.Request.UpdatePayload payload);
-   
+
    @Named("server:delete")
    @DELETE
    @Path("/{serverId}")
    @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
    void deleteServer(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId);
-   
+
    @Named("server:volume:list")
    @GET
    @Path("/{serverId}/volumes")
    @Fallback(EmptyListOnNotFoundOr404.class)
    @SelectJson("items")
    List<Volume> listAttachedVolumes(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId);
-   
+
    @Named("server:volume:attach")
    @POST
    @MapBinder(AttachVolumeRequestBinder.class)
    @ResponseParser(VolumeApi.VolumeParser.class)
    Volume attachVolume(@PayloadParam("volume") Server.Request.AttachVolumePayload payload);
-   
+
    @Named("server:volume:delete")
    @DELETE
    @Path("/{serverId}/volumes/{volumeId}")
    @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
    void detachVolume(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId, @PathParam("volumeId") String volumeId);
-   
+
    @Named("server:volume:get")
    @GET
    @Path("/{serverId}/volumes/{volumeId}")
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
    @ResponseParser(VolumeApi.VolumeParser.class)
    Volume getVolume(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId, @PathParam("volumeId") String volumeId);
-   
+
    @Named("server:cdrom:list")
    @GET
    @Path("/{serverId}/cdroms")
    @Fallback(EmptyListOnNotFoundOr404.class)
    @SelectJson("items")
    List<Image> listAttachedCdroms(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId);
-   
+
    @Named("server:cdrom:attach")
    @POST
    @MapBinder(AttachCdromRequestBinder.class)
    @ResponseParser(ImageApi.ImageParser.class)
    Image attachCdrom(@PayloadParam("cdrom") Server.Request.AttachCdromPayload payload);
-   
+
    @Named("server:cdrom:delete")
    @DELETE
    @Path("/{serverId}/cdroms/{cdRomId}")
    @Fallback(Fallbacks.VoidOnNotFoundOr404.class)
    void detachCdrom(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId, @PathParam("cdRomId") String cdRomId);
-   
+
    @Named("server:cdrom:get")
    @GET
    @Path("/{serverId}/cdroms/{cdRomId}")
    @Fallback(Fallbacks.NullOnNotFoundOr404.class)
    @ResponseParser(ImageApi.ImageParser.class)
    Image getCdrom(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId, @PathParam("cdRomId") String cdRomId);
-   
+
    @Named("server:reboot")
    @POST
    @Path("/{serverId}/reboot")
    void rebootServer(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId);
-   
+
    @Named("server:start")
    @POST
    @Path("/{serverId}/start")
    void startServer(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId);
-   
+
    @Named("server:stop")
    @POST
    @Path("/{serverId}/stop")
    void stopServer(@PathParam("dataCenterId") String dataCenterId, @PathParam("serverId") String serverId);
-   
+
    static final class ServerParser extends ParseJson<Server> {
-      
+
       final ParseId parseService;
-      
-      @Inject ServerParser(Json json, ParseId parseId) {
+
+      @Inject
+      ServerParser(Json json, ParseId parseId) {
          super(json, TypeLiteral.get(Server.class));
          this.parseService = parseId;
       }
@@ -184,10 +185,11 @@ public interface ServerApi extends Closeable {
          try {
             return (V) json.fromJson(this.parseService.parseId(Strings2.toStringAndClose(stream), "datacenters", "dataCenterId"), type);
          } finally {
-            if (stream != null)
+            if (stream != null) {
                stream.close();
+            }
          }
       }
    }
-   
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/ids/NicRef.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/ids/NicRef.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/ids/NicRef.java
new file mode 100644
index 0000000..400f4d1
--- /dev/null
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/ids/NicRef.java
@@ -0,0 +1,34 @@
+/*
+ * 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.jclouds.profitbricks.rest.ids;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class NicRef {
+
+   public abstract String dataCenterId();
+
+   public abstract String serverId();
+
+   public abstract String nicId();
+
+   public static NicRef create(String dataCenterId, String serverId, String nicId) {
+      return new AutoValue_NicRef(dataCenterId, serverId, nicId);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/util/ApiPredicatesModule.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/util/ApiPredicatesModule.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/util/ApiPredicatesModule.java
index 6dc7e0f..2d1252a 100644
--- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/util/ApiPredicatesModule.java
+++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/util/ApiPredicatesModule.java
@@ -16,32 +16,31 @@
  */
 package org.apache.jclouds.profitbricks.rest.util;
 
-import java.util.concurrent.TimeUnit;
-
-import javax.inject.Named;
-import javax.inject.Singleton;
-
+import static com.google.common.base.Preconditions.checkNotNull;
 import com.google.common.base.Predicate;
+import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Provides;
+import java.util.concurrent.TimeUnit;
+import javax.inject.Named;
+import javax.inject.Singleton;
 import org.apache.jclouds.profitbricks.rest.ProfitBricksApi;
+import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_MAX_PERIOD;
 import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_PERIOD;
 import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_PREDICATE_DATACENTER;
 import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_TIMEOUT;
 import org.apache.jclouds.profitbricks.rest.domain.ProvisioningState;
 import org.apache.jclouds.profitbricks.rest.domain.Server;
-import com.google.inject.AbstractModule;
-import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_MAX_PERIOD;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.TIMEOUT_NODE_RUNNING;
-import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.TIMEOUT_NODE_SUSPENDED;
 import org.apache.jclouds.profitbricks.rest.ids.ServerRef;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
 import static org.jclouds.util.Predicates2.retry;
 
 public class ApiPredicatesModule extends AbstractModule {
 
    @Override
-   protected void configure() {}
+   protected void configure() {
+   }
 
    @Provides
    @Singleton
@@ -59,7 +58,7 @@ public class ApiPredicatesModule extends AbstractModule {
               api, Server.Status.RUNNING),
               constants.pollTimeout(), constants.pollPeriod(), constants.pollMaxPeriod(), TimeUnit.SECONDS);
    }
-   
+
    @Provides
    @Named(TIMEOUT_NODE_SUSPENDED)
    Predicate<ServerRef> provideServerSuspendedPredicate(final ProfitBricksApi api, ComputeConstants constants) {
@@ -67,7 +66,7 @@ public class ApiPredicatesModule extends AbstractModule {
               api, Server.Status.SHUTOFF),
               constants.pollTimeout(), constants.pollPeriod(), constants.pollMaxPeriod(), TimeUnit.SECONDS);
    }
-   
+
    static class DataCenterProvisioningStatePredicate implements Predicate<String> {
 
       private final ProfitBricksApi api;
@@ -99,12 +98,13 @@ public class ApiPredicatesModule extends AbstractModule {
       @Override
       public boolean apply(ServerRef serverRef) {
          checkNotNull(serverRef, "serverRef");
-         
+
          Server server = api.serverApi().getServer(serverRef.dataCenterId(), serverRef.serverId());
-         
-         if (server == null || server.properties().vmState() == null)
+
+         if (server == null || server.properties().vmState() == null) {
             return false;
-         
+         }
+
          return server.properties().vmState() == expectedStatus;
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceLiveTest.java b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceLiveTest.java
new file mode 100644
index 0000000..de6a2fb
--- /dev/null
+++ b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceLiveTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.jclouds.profitbricks.rest.compute;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import com.google.inject.Module;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.jclouds.compute.domain.ExecResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
+import static org.jclouds.compute.predicates.NodePredicates.inGroup;
+import org.jclouds.logging.config.LoggingModule;
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", singleThreaded = true, testName = "ProfitBricksComputeServiceLiveTest")
+public class ProfitBricksComputeServiceLiveTest extends BaseComputeServiceLiveTest {
+
+   public ProfitBricksComputeServiceLiveTest() {
+      provider = "profitbricks-rest";
+   }
+
+   @Override
+   protected Module getSshModule() {
+      return new SshjSshClientModule();
+   }
+
+   @Override
+   protected LoggingModule getLoggingModule() {
+      return new SLF4JLoggingModule();
+   }
+
+   @Override
+   public void testOptionToNotBlock() throws Exception {
+      // ProfitBricks implementation intentionally blocks until the node is 'AVAILABLE'
+   }
+
+   @Override
+   protected void checkTagsInNodeEquals(NodeMetadata node, ImmutableSet<String> tags) {
+      // ProfitBricks doesn't support tags
+   }
+
+   @Override
+   protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
+      // ProfitBricks doesn't support user metadata
+   }
+
+   @Override
+   protected void checkResponseEqualsHostname(ExecResponse execResponse, NodeMetadata node1) {
+      // ProfitBricks doesn't support hostname
+   }
+
+   @Override
+   protected void checkOsMatchesTemplate(NodeMetadata node) {
+      // Not enough description from API to match template
+   }
+
+   @Override
+   @Test
+   public void testCreateNodeWithCustomHardware() throws Exception {
+      Template template = buildTemplate(templateBuilder()
+              .hardwareId("automatic:cores=2;ram=2048;disk=20"));
+      try {
+         NodeMetadata node = getOnlyElement(client.createNodesInGroup(group + "custom", 1, template));
+         assertThat(node.getHardware().getRam()).isEqualTo(2048);
+         assertThat(node.getHardware().getProcessors().get(0).getCores()).isEqualTo(2);
+         assertThat(node.getHardware().getVolumes().get(0).getSize()).isEqualTo(20);
+         assertThat(node.getHardware().getId()).isEqualTo("cpu=2,ram=2048,disk=20");
+      } finally {
+         client.destroyNodesMatching(inGroup(group + "custom"));
+      }
+   }
+
+   @Test
+   public void testCreateNodeWithCustomHardwareUsingMins() throws Exception {
+      Template template = buildTemplate(templateBuilder()
+              .minCores(2).minRam(2048).minDisk(20));
+      try {
+         NodeMetadata node = getOnlyElement(client.createNodesInGroup(group + "custom", 1, template));
+         assertThat(node.getHardware().getRam()).isEqualTo(2048);
+         assertThat(node.getHardware().getProcessors().get(0).getCores()).isEqualTo(2);
+         assertThat(node.getHardware().getVolumes().get(0).getSize()).isEqualTo(20);
+         assertThat(node.getHardware().getId()).isEqualTo("cpu=2,ram=2048,disk=20");
+      } finally {
+         client.destroyNodesMatching(inGroup(group + "custom"));
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksTemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksTemplateBuilderLiveTest.java b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksTemplateBuilderLiveTest.java
new file mode 100644
index 0000000..afe1be2
--- /dev/null
+++ b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksTemplateBuilderLiveTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.jclouds.profitbricks.rest.compute;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "ProfitBricksTemplateBuilderLiveTest", singleThreaded = true)
+public class ProfitBricksTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
+
+   public ProfitBricksTemplateBuilderLiveTest() {
+      this.provider = "profitbricks-rest";
+   }
+
+   @Override
+   protected Set<String> getIso3166Codes() {
+      return ImmutableSet.of("DE-BW", "DE-HE", "US-NV");
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/concurrent/ProvisioningManagerTest.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/concurrent/ProvisioningManagerTest.java b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/concurrent/ProvisioningManagerTest.java
new file mode 100644
index 0000000..08b90e4
--- /dev/null
+++ b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/concurrent/ProvisioningManagerTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.jclouds.profitbricks.rest.compute.concurrent;
+
+import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
+import static java.util.logging.Logger.getAnonymousLogger;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.base.Throwables;
+
+@Test(groups = "unit", testName = "ProvisioningManagerTest")
+public class ProvisioningManagerTest {
+
+   @Test
+   public void testProvision() throws IOException {
+      ProvisioningManager manager = new ProvisioningManager();
+      AtomicInteger completedJobs = new AtomicInteger(0);
+
+      try {
+         for (int i = 0; i < 5; i++) {
+            manager.provision(new MockJob(200, "slow", completedJobs));
+            manager.provision(new MockJob(0, "fast", completedJobs));
+            manager.provision(new MockJob(100, "normal", completedJobs));
+         }
+      } finally {
+         manager.close();
+      }
+
+      assertEquals(completedJobs.get(), 15);
+   }
+
+   @Test
+   public void testProvisionInterrupted() {
+      ProvisioningManager manager = new ProvisioningManager();
+      AtomicInteger completedJobs = new AtomicInteger(0);
+
+      manager.provision(new ShutdownExecutorJob(manager, completedJobs));
+      manager.provision(new MockJob(0, "rejected", completedJobs));
+
+      assertEquals(completedJobs.get(), 1);
+   }
+
+   private static class MockJob extends ProvisioningJob {
+
+      private final long delay;
+      private final AtomicInteger completedJobs;
+
+      public MockJob(long delay, String group, AtomicInteger completedJobs) {
+         super(sleepPredicate(delay), group, Suppliers.ofInstance((Object) 0));
+         this.delay = delay;
+         this.completedJobs = completedJobs;
+      }
+
+      @Override
+      public Integer call() throws Exception {
+         getAnonymousLogger().info("ProvisioningManagerTest: Starting " + this);
+         super.call();
+         getAnonymousLogger().info("ProvisioningManagerTest: Completed " + this);
+         return completedJobs.incrementAndGet();
+      }
+
+      @Override
+      public String toString() {
+         return "MockJob [id=" + hashCode() + ", group=" + getGroup() + ", delay=" + delay + "]";
+      }
+   }
+
+   private static class ShutdownExecutorJob extends ProvisioningJob {
+
+      public ShutdownExecutorJob(final ProvisioningManager manager, final AtomicInteger completedJobs) {
+         super(Predicates.<String>alwaysTrue(), "shutdown", new Supplier<Object>() {
+            @Override
+            public Integer get() {
+               try {
+                  manager.close();
+                  return completedJobs.incrementAndGet();
+               } catch (IOException ex) {
+                  throw Throwables.propagate(ex);
+               }
+            }
+         });
+      }
+   }
+
+   private static Predicate<String> sleepPredicate(final long delay) {
+      return new Predicate<String>() {
+         @Override
+         public boolean apply(String input) {
+            sleepUninterruptibly(delay, TimeUnit.MILLISECONDS);
+            return true;
+         }
+      };
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/5742745e/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/config/StatusPredicateTest.java
----------------------------------------------------------------------
diff --git a/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/config/StatusPredicateTest.java b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/config/StatusPredicateTest.java
new file mode 100644
index 0000000..69e21f4
--- /dev/null
+++ b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/config/StatusPredicateTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.jclouds.profitbricks.rest.compute.config;
+
+import com.google.common.base.Predicate;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import java.util.concurrent.TimeUnit;
+import org.apache.jclouds.profitbricks.rest.compute.config.ProfitBricksComputeServiceContextModule.DataCenterProvisioningStatePredicate;
+import org.apache.jclouds.profitbricks.rest.compute.config.ProfitBricksComputeServiceContextModule.ServerStatusPredicate;
+import org.apache.jclouds.profitbricks.rest.compute.config.ProfitBricksComputeServiceContextModule.SnapshotProvisioningStatePredicate;
+import org.apache.jclouds.profitbricks.rest.domain.DataCenter;
+import org.apache.jclouds.profitbricks.rest.domain.Server;
+import org.apache.jclouds.profitbricks.rest.domain.Snapshot;
+import org.apache.jclouds.profitbricks.rest.domain.State;
+import org.apache.jclouds.profitbricks.rest.ids.ServerRef;
+import org.apache.jclouds.profitbricks.rest.internal.BaseProfitBricksApiMockTest;
+import org.jclouds.util.Predicates2;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+
+/**
+ * Test class for {@link DataCenterProvisioningStatePredicate} and
+ * {@link ServerStatusPredicate}
+ */
+@Test(groups = "unit", testName = "ProvisioningStatusPollingPredicateTest", singleThreaded = true)
+public class StatusPredicateTest extends BaseProfitBricksApiMockTest {
+
+   @Test
+   public void testDataCenterPredicate() throws Exception {
+
+      String payloadInProcess = stringFromResource("/compute/predicate/datacenter-inprocess.json");
+      String payloadAvailable = stringFromResource("/compute/predicate/datacenter.json");
+
+      // wait 3 times
+      server.enqueue(new MockResponse().setBody(payloadInProcess));
+      server.enqueue(new MockResponse().setBody(payloadInProcess));
+      server.enqueue(new MockResponse().setBody(payloadInProcess));
+      server.enqueue(new MockResponse().setBody(payloadAvailable));
+
+      server.enqueue(new MockResponse().setBody(payloadAvailable));
+
+      Predicate<String> waitUntilAvailable = Predicates2.retry(
+              new DataCenterProvisioningStatePredicate(api, State.AVAILABLE),
+              30l, 1l, TimeUnit.SECONDS);
+
+      String id = "datacenter-id,aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
+
+      waitUntilAvailable.apply(id);
+
+      DataCenter dataCenter = api.dataCenterApi().getDataCenter(id);
+      State finalState = dataCenter.metadata().state();
+      assertEquals(finalState, State.AVAILABLE);
+
+   }
+
+   @Test
+   public void testServerPredicate() throws Exception {
+
+      String payloadInProcess = stringFromResource("/compute/predicate/server-inprocess.json");
+      String payloadAvailable = stringFromResource("/compute/predicate/server.json");
+
+      // wait 3 times
+      server.enqueue(new MockResponse().setBody(payloadInProcess));
+      server.enqueue(new MockResponse().setBody(payloadInProcess));
+      server.enqueue(new MockResponse().setBody(payloadInProcess));
+      server.enqueue(new MockResponse().setBody(payloadAvailable));
+
+      server.enqueue(new MockResponse().setBody(payloadAvailable));
+
+      Predicate<ServerRef> waitUntilAvailable = Predicates2.retry(
+              new ServerStatusPredicate(api, Server.Status.RUNNING),
+              30l, 1l, TimeUnit.SECONDS);
+
+      waitUntilAvailable.apply(ServerRef.create("datacenter-id", "server-id"));
+      Server remoteServer = api.serverApi().getServer("datacenter-id", "server-id");
+      assertEquals(remoteServer.properties().vmState(), Server.Status.RUNNING);
+
+   }
+
+   @Test
+   public void testSnapshotPredicate() throws Exception {
+
+      String payloadInProcess = stringFromResource("/compute/predicate/snapshot-inprocess.json");
+      String payloadAvailable = stringFromResource("/compute/predicate/snapshot.json");
+
+      // wait 3 times
+      server.enqueue(new MockResponse().setBody(payloadInProcess));
+      server.enqueue(new MockResponse().setBody(payloadInProcess));
+      server.enqueue(new MockResponse().setBody(payloadInProcess));
+      server.enqueue(new MockResponse().setBody(payloadAvailable));
+
+      server.enqueue(new MockResponse().setBody(payloadAvailable));
+
+      Predicate<String> waitUntilAvailable = Predicates2.retry(
+              new SnapshotProvisioningStatePredicate(api, State.AVAILABLE),
+              30l, 1l, TimeUnit.SECONDS);
+
+      String id = "qswdefrg-qaws-qaws-defe-rgrgdsvcxbrh";
+
+      waitUntilAvailable.apply(id);
+      Snapshot snapshot = api.snapshotApi().get(id);
+      assertEquals(snapshot.metadata().state().toString(), State.AVAILABLE.toString());
+
+   }
+
+}