You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by de...@apache.org on 2016/02/19 16:33:23 UTC

[13/35] jclouds git commit: JCLOUDS-702: JCloud ProfitBricks provider - NIC & Firewall API

JCLOUDS-702: JCloud ProfitBricks provider - NIC & Firewall API


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

Branch: refs/heads/master
Commit: de2e5e01b58b3859f7ea78e8c4d282fe735ca71a
Parents: 2a219a9
Author: Reijhanniel Jearl Campos <de...@gmail.com>
Authored: Wed Feb 25 23:27:42 2015 +0800
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu Feb 26 15:49:16 2015 +0100

----------------------------------------------------------------------
 .../jclouds/profitbricks/ProfitBricksApi.java   |   8 +
 .../AddFirewallRuleToNicRequestBinder.java      |  53 +++
 .../binder/firewall/FirewallBinder.java         |  95 +++++
 .../binder/nic/CreateNicRequestBinder.java      |  46 +++
 .../binder/nic/SetInternetAccessBinder.java     |  42 ++
 .../binder/nic/UpdateNicRequestBinder.java      |  46 +++
 .../internal/ProvisioningStatusAware.java       |   2 +-
 .../ProvisioningStatusPollingPredicate.java     |   7 +-
 .../jclouds/profitbricks/domain/Firewall.java   | 366 ++++++++++++++++++
 .../org/jclouds/profitbricks/domain/Nic.java    | 379 +++++++++++++++++++
 .../org/jclouds/profitbricks/domain/Server.java |  29 +-
 .../jclouds/profitbricks/domain/Storage.java    |   1 +
 .../internal/FirewallRuleCommonProperties.java  |  44 +++
 .../profitbricks/features/DataCenterApi.java    |  12 +-
 .../profitbricks/features/FirewallApi.java      |  93 +++++
 .../jclouds/profitbricks/features/NicApi.java   |  84 ++++
 .../profitbricks/features/ServerApi.java        |  20 +-
 .../profitbricks/features/StorageApi.java       |  11 +-
 ...usFromPayloadHttpCommandExecutorService.java |  76 ++--
 .../parser/BaseProfitBricksResponseHandler.java |   4 +
 .../DataCenterInfoResponseHandler.java          |  54 ++-
 .../firewall/BaseFirewallResponseHandler.java   |  69 ++++
 .../firewall/FirewallListResponseHandler.java   |  64 ++++
 .../firewall/FirewallResponseHandler.java       |  63 +++
 .../rule/BaseFirewallRuleResponseHandler.java   |  54 +++
 .../rule/FirewallRuleListResponseHandler.java   |  54 +++
 .../http/parser/nic/BaseNicResponseHandler.java |  82 ++++
 .../http/parser/nic/NicListResponseHandler.java |  65 ++++
 .../http/parser/nic/NicResponseHandler.java     |  58 +++
 .../server/BaseServerResponseHandler.java       |  40 +-
 .../server/ServerInfoResponseHandler.java       |  32 +-
 .../server/ServerListResponseHandler.java       |  44 ++-
 .../storage/StorageListResponseHandler.java     |   9 +-
 .../jclouds/profitbricks/util/MacAddresses.java |  29 ++
 .../AddFirewallRuleToNicRequestBinderTest.java  |  64 ++++
 .../binder/firewall/FirewallBinderTest.java     | 131 +++++++
 .../binder/nic/CreateNicRequestBinderTest.java  |  53 +++
 .../binder/nic/SetInternetAccessBinderTest.java |  48 +++
 .../binder/nic/UpdateNicRequestBinderTest.java  |  54 +++
 .../domain/FirewallRuleBuilderTest.java         |  82 ++++
 .../features/FirewallApiLiveTest.java           | 146 +++++++
 .../features/FirewallApiMockTest.java           | 324 ++++++++++++++++
 .../profitbricks/features/NicApiLiveTest.java   | 136 +++++++
 .../profitbricks/features/NicApiMockTest.java   | 222 +++++++++++
 .../DataCenterInfoResponseHandlerTest.java      |  44 ++-
 .../FirewallListResponseHandlerTest.java        |  87 +++++
 .../firewall/FirewallResponseHandlerTest.java   |  71 ++++
 .../parser/nic/NicListResponseHandlerTest.java  |  95 +++++
 .../http/parser/nic/NicResponseHandlerTest.java |  66 ++++
 .../server/ServerInfoResponseHandlerTest.java   |  36 ++
 .../server/ServerListResponseHandlerTest.java   |  71 ++++
 .../profitbricks/util/MacAddressesTest.java     |  45 +++
 .../test/resources/datacenter/datacenter.xml    |   3 +-
 .../resources/firewall/firewall-activate.xml    |  12 +
 .../resources/firewall/firewall-addtonic.xml    |  23 ++
 .../resources/firewall/firewall-deactivate.xml  |  12 +
 .../test/resources/firewall/firewall-delete.xml |  12 +
 .../test/resources/firewall/firewall-remove.xml |  12 +
 .../src/test/resources/firewall/firewall.xml    |  23 ++
 .../src/test/resources/firewall/firewalls.xml   |  39 ++
 .../src/test/resources/nic/nic-create.xml       |  13 +
 .../src/test/resources/nic/nic-delete.xml       |   9 +
 .../test/resources/nic/nic-internetaccess.xml   |  11 +
 .../src/test/resources/nic/nic-update.xml       |  15 +
 .../profitbricks/src/test/resources/nic/nic.xml |  27 ++
 .../src/test/resources/nic/nics.xml             |  49 +++
 .../src/test/resources/server/servers.xml       |   1 +
 67 files changed, 4052 insertions(+), 119 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksApi.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksApi.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksApi.java
index 4cfe6e8..49d7e8c 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksApi.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/ProfitBricksApi.java
@@ -19,7 +19,9 @@ package org.jclouds.profitbricks;
 import java.io.Closeable;
 
 import org.jclouds.profitbricks.features.DataCenterApi;
+import org.jclouds.profitbricks.features.FirewallApi;
 import org.jclouds.profitbricks.features.ImageApi;
+import org.jclouds.profitbricks.features.NicApi;
 import org.jclouds.profitbricks.features.ServerApi;
 import org.jclouds.profitbricks.features.StorageApi;
 import org.jclouds.rest.annotations.Delegate;
@@ -37,4 +39,10 @@ public interface ProfitBricksApi extends Closeable {
 
    @Delegate
    StorageApi storageApi();
+
+   @Delegate
+   NicApi nicApi();
+
+   @Delegate
+   FirewallApi firewallApi();
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/firewall/AddFirewallRuleToNicRequestBinder.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/firewall/AddFirewallRuleToNicRequestBinder.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/firewall/AddFirewallRuleToNicRequestBinder.java
new file mode 100644
index 0000000..9bdbf76
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/firewall/AddFirewallRuleToNicRequestBinder.java
@@ -0,0 +1,53 @@
+/*
+ * 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.binder.firewall;
+
+import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
+import org.jclouds.profitbricks.domain.Firewall;
+import static java.lang.String.format;
+
+public class AddFirewallRuleToNicRequestBinder extends BaseProfitBricksRequestBinder<Firewall.Request.AddRulePayload> {
+
+   private final StringBuilder requestBuilder;
+
+   AddFirewallRuleToNicRequestBinder() {
+      super("firewall");
+      this.requestBuilder = new StringBuilder(128);
+   }
+
+   @Override
+   protected String createPayload(Firewall.Request.AddRulePayload payload) {
+      requestBuilder.append("<ws:addFirewallRulesToNic>")
+              .append(format("<nicId>%s</nicId>", payload.nicId()));
+      for (Firewall.RuleWithIcmp rule : payload.rules())
+         requestBuilder
+                 .append("<request>")
+                 .append(formatIfNotEmpty("<icmpCode>%s</icmpCode>", rule.icmpCode()))
+                 .append(formatIfNotEmpty("<icmpType>%s</icmpType>", rule.icmpType()))
+                 .append(formatIfNotEmpty("<name>%s</name>", rule.name()))
+                 .append(formatIfNotEmpty("<portRangeEnd>%s</portRangeEnd>", rule.portRangeEnd()))
+                 .append(formatIfNotEmpty("<portRangeStart>%s</portRangeStart>", rule.portRangeStart()))
+                 .append(formatIfNotEmpty("<protocol>%s</protocol>", rule.protocol()))
+                 .append(formatIfNotEmpty("<sourceIp>%s</sourceIp>", rule.sourceIp()))
+                 .append(formatIfNotEmpty("<sourceMac>%s</sourceMac>", rule.sourceMac()))
+                 .append(formatIfNotEmpty("<targetIp>%s</targetIp>", rule.targetIp()))
+                 .append("</request>");
+      requestBuilder.append("</ws:addFirewallRulesToNic>");
+      return requestBuilder.toString();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/firewall/FirewallBinder.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/firewall/FirewallBinder.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/firewall/FirewallBinder.java
new file mode 100644
index 0000000..a1f03c2
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/firewall/FirewallBinder.java
@@ -0,0 +1,95 @@
+/*
+ * 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.binder.firewall;
+
+import static java.lang.String.format;
+
+import java.util.List;
+
+import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
+
+import com.google.common.base.Strings;
+
+public abstract class FirewallBinder extends BaseProfitBricksRequestBinder<List<String>> {
+
+   protected final StringBuilder requestBuilder;
+
+   FirewallBinder() {
+      super("ids");
+      this.requestBuilder = new StringBuilder(128);
+   }
+
+   protected void bindListWithTag(List<String> ids, String tag) {
+      if (ids == null || ids.isEmpty() || Strings.isNullOrEmpty(tag))
+         return;
+      for (String id : ids)
+         requestBuilder.append(format("<%s>%s</%s>", tag, id, tag));
+   }
+
+   public static class ActivateFirewallRequestBinder extends FirewallBinder {
+
+      @Override
+      protected String createPayload(List<String> payload) {
+         requestBuilder.append("<ws:activateFirewalls>");
+         bindListWithTag(payload, "firewallIds");
+         requestBuilder.append("</ws:activateFirewalls>");
+
+         return requestBuilder.toString();
+      }
+
+   }
+
+   public static class DeactivateFirewallRequestBinder extends FirewallBinder {
+
+      @Override
+      protected String createPayload(List<String> payload) {
+         requestBuilder.append("<ws:deactivateFirewalls>");
+         bindListWithTag(payload, "firewallIds");
+         requestBuilder.append("</ws:deactivateFirewalls>");
+
+         return requestBuilder.toString();
+      }
+
+   }
+
+   public static class DeleteFirewallRequestBinder extends FirewallBinder {
+
+      @Override
+      protected String createPayload(List<String> payload) {
+         requestBuilder.append("<ws:deleteFirewalls>");
+         bindListWithTag(payload, "firewallIds");
+         requestBuilder.append("</ws:deleteFirewalls>");
+
+         return requestBuilder.toString();
+      }
+
+   }
+
+   public static class RemoveFirewallRuleRequestBinder extends FirewallBinder {
+
+      @Override
+      protected String createPayload(List<String> payload) {
+         requestBuilder.append("<ws:removeFirewallRules>");
+         bindListWithTag(payload, "firewallRuleIds");
+         requestBuilder.append("</ws:removeFirewallRules>");
+
+         return requestBuilder.toString();
+      }
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/CreateNicRequestBinder.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/CreateNicRequestBinder.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/CreateNicRequestBinder.java
new file mode 100644
index 0000000..f7dbdb3
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/CreateNicRequestBinder.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.jclouds.profitbricks.binder.nic;
+
+import static java.lang.String.format;
+import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
+import org.jclouds.profitbricks.domain.Nic;
+
+public class CreateNicRequestBinder extends BaseProfitBricksRequestBinder<Nic.Request.CreatePayload> {
+
+   private final StringBuilder requestBuilder;
+
+   CreateNicRequestBinder() {
+      super("nic");
+      this.requestBuilder = new StringBuilder(128 * 2);
+   }
+
+   @Override
+   protected String createPayload(Nic.Request.CreatePayload payload) {
+      requestBuilder.append("<ws:createNic>")
+              .append("<request>")
+              .append(formatIfNotEmpty("<ip>%s</ip>", payload.ip()))
+              .append(formatIfNotEmpty("<nicName>%s</nicName>", payload.name()))
+              .append(formatIfNotEmpty("<dhcpActive>%s</dhcpActive>", payload.dhcpActive()))
+              .append(format("<serverId>%s</serverId>", payload.serverId()))
+              .append(format("<lanId>%s</lanId>", payload.lanId()))
+              .append("</request>")
+              .append("</ws:createNic>");
+      return requestBuilder.toString();
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/SetInternetAccessBinder.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/SetInternetAccessBinder.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/SetInternetAccessBinder.java
new file mode 100644
index 0000000..acdc809
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/SetInternetAccessBinder.java
@@ -0,0 +1,42 @@
+/*
+ * 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.binder.nic;
+
+import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
+import org.jclouds.profitbricks.domain.Nic;
+
+import static java.lang.String.format;
+
+public class SetInternetAccessBinder extends BaseProfitBricksRequestBinder<Nic.Request.SetInternetAccessPayload> {
+
+   private final StringBuilder requestBuilder;
+
+   SetInternetAccessBinder() {
+      super("nic");
+      this.requestBuilder = new StringBuilder(128);
+   }
+
+   @Override
+   protected String createPayload(Nic.Request.SetInternetAccessPayload payload) {
+      requestBuilder.append("<ws:setInternetAccess>")
+              .append(format("<dataCenterId>%s</dataCenterId>", payload.dataCenterId()))
+              .append(format("<lanId>%s</lanId>", payload.lanId()))
+              .append(format("<internetAccess>%s</internetAccess>", payload.internetAccess()))
+              .append("</ws:setInternetAccess>");
+      return requestBuilder.toString();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/UpdateNicRequestBinder.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/UpdateNicRequestBinder.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/UpdateNicRequestBinder.java
new file mode 100644
index 0000000..f1e9d83
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/binder/nic/UpdateNicRequestBinder.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.jclouds.profitbricks.binder.nic;
+
+import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
+import org.jclouds.profitbricks.domain.Nic;
+
+import static java.lang.String.format;
+
+public class UpdateNicRequestBinder extends BaseProfitBricksRequestBinder<Nic.Request.UpdatePayload> {
+
+   private final StringBuilder requestBuilder;
+
+   UpdateNicRequestBinder() {
+      super("nic");
+      this.requestBuilder = new StringBuilder(128 * 2);
+   }
+
+   @Override
+   protected String createPayload(Nic.Request.UpdatePayload payload) {
+      requestBuilder.append("<ws:updateNic>")
+              .append("<request>")
+              .append(format("<nicId>%s</nicId>", payload.id()))
+              .append(formatIfNotEmpty("<ip>%s</ip>", payload.ip()))
+              .append(formatIfNotEmpty("<nicName>%s</nicName>", payload.name()))
+              .append(formatIfNotEmpty("<dhcpActive>%s</dhcpActive>", payload.dhcpActive()))
+              .append(formatIfNotEmpty("<lanId>%s</lanId>", payload.lanId()))
+              .append("</request>")
+              .append("</ws:updateNic>");
+      return requestBuilder.toString();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusAware.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusAware.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusAware.java
index f573eb0..7a11009 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusAware.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusAware.java
@@ -23,5 +23,5 @@ package org.jclouds.profitbricks.compute.internal;
  */
 public enum ProvisioningStatusAware {
 
-   DATACENTER, SERVER, STORAGE;
+   DATACENTER, SERVER, STORAGE, NIC;
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusPollingPredicate.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusPollingPredicate.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusPollingPredicate.java
index 8a8a787..7606cac 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusPollingPredicate.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/internal/ProvisioningStatusPollingPredicate.java
@@ -26,8 +26,9 @@ import com.google.common.base.Predicate;
 /**
  * A custom predicate for waiting until a virtual resource satisfies the given expected status
  * <p>
- * Performing api requests on a datacenter that is not {@link ProvisioningState#AVAILABLE} is not allowed. On some cases, the API user gets
- * blocked from further requests, and will then need to contact tech support for api lock release.
+ * Performing api requests on a datacenter that is not {@link ProvisioningState#AVAILABLE} is not allowed. On some
+ * cases, the API user gets blocked from further requests, and will then need to contact tech support for api lock
+ * release.
  */
 public class ProvisioningStatusPollingPredicate implements Predicate<String> {
 
@@ -51,6 +52,8 @@ public class ProvisioningStatusPollingPredicate implements Predicate<String> {
             return expect == api.serverApi().getServer(input).state();
          case STORAGE:
             return expect == api.storageApi().getStorage(input).state();
+         case NIC:
+            return expect == api.nicApi().getNic(input).state();
          default:
             throw new IllegalArgumentException("Unknown domain '" + domain + "'");
       }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Firewall.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Firewall.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Firewall.java
new file mode 100644
index 0000000..626a4b1
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Firewall.java
@@ -0,0 +1,366 @@
+/*
+ * 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.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.jclouds.profitbricks.util.MacAddresses.isMacAddress;
+
+import com.google.auto.value.AutoValue;
+
+import java.util.List;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.profitbricks.domain.internal.FirewallRuleCommonProperties;
+
+import com.google.common.collect.ImmutableList;
+
+import autovalue.shaded.com.google.common.common.collect.Lists;
+import static com.google.common.net.InetAddresses.isInetAddress;
+
+@AutoValue
+public abstract class Firewall {
+
+   public enum Protocol {
+
+      TCP, UDP, ICMP, ANY, UNRECOGNIZED;
+
+      public static Protocol fromValue(String value) {
+         try {
+            return valueOf(value);
+         } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+         }
+      }
+   }
+
+   @Nullable
+   public abstract String id();
+
+   @Nullable
+   public abstract String nicId();
+
+   public abstract boolean active();
+
+   @Nullable
+   public abstract ProvisioningState state();
+
+   @Nullable
+   public abstract List<Rule> rules();
+
+   public static Firewall create(String id, String nicId, boolean active, ProvisioningState provisioningState,
+           List<Rule> rules) {
+      return new AutoValue_Firewall(id, nicId, active, provisioningState,
+              rules != null ? ImmutableList.copyOf(rules) : ImmutableList.<Rule>of());
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public static final class Request {
+
+      public static AddRulePayload.Builder ruleAddingBuilder() {
+         return new AddRulePayload.Builder();
+      }
+
+      @AutoValue
+      public abstract static class AddRulePayload {
+
+         public abstract String nicId();
+
+         public abstract List<RuleWithIcmp> rules();
+
+         public static AddRulePayload create(String nicId, List<RuleWithIcmp> rules) {
+            return new AutoValue_Firewall_Request_AddRulePayload(nicId, rules);
+         }
+
+         public static class Builder {
+
+            private String nicId;
+            private List<RuleWithIcmp> rules = Lists.newArrayList();
+
+            public Builder nicId(String nicId) {
+               this.nicId = nicId;
+               return this;
+            }
+
+            public Builder rules(List<RuleWithIcmp> rules) {
+               this.rules = rules;
+               return this;
+            }
+
+            public RuleWithIcmp.Builder newRule() {
+               return new RuleWithIcmp.Builder(this);
+            }
+
+            public Builder addRule(RuleWithIcmp rule) {
+               this.rules.add(rule);
+               return this;
+            }
+
+            public AddRulePayload build() {
+               return AddRulePayload.create(nicId, rules);
+            }
+         }
+      }
+   }
+
+   public static class Builder {
+
+      private String id;
+      private String nicId;
+      private boolean active;
+
+      private ProvisioningState state;
+      private List<Rule> rules;
+
+      public Builder id(String id) {
+         this.id = id;
+         return this;
+      }
+
+      public Builder nicId(String nicId) {
+         this.nicId = nicId;
+         return this;
+      }
+
+      public Builder active(boolean active) {
+         this.active = active;
+         return this;
+      }
+
+      public Builder state(ProvisioningState state) {
+         this.state = state;
+         return this;
+      }
+
+      public Builder rules(List<Rule> firewallRules) {
+         this.rules = firewallRules;
+         return this;
+      }
+
+      public Builder fromFirewall(Firewall in) {
+         return this.id(in.id()).nicId(in.nicId()).active(in.active()).state(in.state())
+                 .rules(in.rules());
+      }
+
+      public Firewall build() {
+         return Firewall.create(id, nicId, active, state, rules);
+      }
+   }
+
+   public abstract static class RuleBuilder<B extends RuleBuilder, D extends FirewallRuleCommonProperties> {
+
+      protected String name;
+      protected Integer portRangeEnd;
+      protected Integer portRangeStart;
+      protected Protocol protocol;
+      protected String sourceIp;
+      protected String sourceMac;
+      protected String targetIp;
+
+      public B name(String name) {
+         this.name = name;
+         return self();
+      }
+
+      public B portRangeEnd(Integer portRangeEnd) {
+         this.portRangeEnd = portRangeEnd;
+         return self();
+      }
+
+      public B portRangeStart(Integer portRangeStart) {
+         this.portRangeStart = portRangeStart;
+         return self();
+      }
+
+      public B protocol(Protocol protocol) {
+         this.protocol = protocol;
+         return self();
+      }
+
+      public B sourceIp(String sourceIp) {
+         this.sourceIp = sourceIp;
+         return self();
+      }
+
+      public B sourceMac(String sourceMac) {
+         this.sourceMac = sourceMac;
+         return self();
+      }
+
+      public B targetIp(String targetIp) {
+         this.targetIp = targetIp;
+         return self();
+      }
+
+      public abstract B self();
+
+      public abstract D build();
+
+      protected void checkPortRange() {
+         checkArgument(!(portRangeEnd == null ^ portRangeStart == null), "Port range must be both present or null");
+         if (portRangeEnd != null) {
+            checkArgument(protocol == Protocol.TCP || protocol == Protocol.UDP, "Port range can only be set for TCP or UDP");
+            checkArgument(portRangeEnd > portRangeStart, "portRangeEnd must be greater than portRangeStart");
+            checkArgument(portRangeEnd >= 1 && portRangeEnd <= 65534, "Port range end must be 1 to 65534");
+            checkArgument(portRangeStart >= 1 && portRangeStart <= 65534, "Port range start must be 1 to 65534");
+         }
+      }
+
+      protected void checkMac() {
+         if (sourceMac != null)
+            checkArgument(isMacAddress(sourceMac), "Source MAC must match pattern 'aa:bb:cc:dd:ee:ff'");
+      }
+
+      protected void checkIp() {
+         if (sourceIp != null)
+            checkArgument(isInetAddress(sourceIp), "Source IP is invalid");
+         if (targetIp != null)
+            checkArgument(isInetAddress(targetIp), "Target IP is invalid");
+      }
+
+      protected void checkFields() {
+         checkMac();
+         checkPortRange();
+         checkIp();
+      }
+
+   }
+
+   @AutoValue
+   public abstract static class Rule implements FirewallRuleCommonProperties {
+
+      @Nullable
+      public abstract String id();
+
+      public static Rule create(String id, String name, Integer portRangeEnd, Integer portRangeStart,
+              Protocol protocol, String sourceIp, String sourceMac, String targetIp) {
+         return new AutoValue_Firewall_Rule(name, portRangeEnd, portRangeStart, protocol, sourceIp, sourceMac,
+                 targetIp, id);
+      }
+
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      public static class Builder extends RuleBuilder<Builder, Rule> {
+
+         private String id;
+
+         public Builder id(String id) {
+            this.id = id;
+            return self();
+         }
+
+         @Override
+         public Builder self() {
+            return this;
+         }
+
+         @Override
+         public Rule build() {
+            checkFields();
+            return Rule.create(id, name, portRangeEnd, portRangeStart, protocol, sourceIp, sourceMac, targetIp);
+         }
+
+      }
+   }
+
+   @AutoValue
+   public abstract static class RuleWithIcmp implements FirewallRuleCommonProperties {
+
+      @Nullable
+      public abstract Integer icmpCode();
+
+      @Nullable
+      public abstract Integer icmpType();
+
+      public static RuleWithIcmp create(Integer icmpCode, Integer icmpType, String name, Integer portRangeEnd,
+              Integer portRangeStart, Protocol protocol, String sourceIp, String sourceMac, String targetIp) {
+         return new AutoValue_Firewall_RuleWithIcmp(name, portRangeEnd, portRangeStart, protocol, sourceIp, sourceMac,
+                 targetIp, icmpCode, icmpType);
+      }
+
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      public static class Builder extends RuleBuilder<Builder, RuleWithIcmp> {
+
+         private Request.AddRulePayload.Builder parentBuilder;
+
+         private Integer icmpCode;
+         private Integer icmpType;
+
+         public Builder() {
+
+         }
+
+         private Builder(Request.AddRulePayload.Builder parentBuilder) {
+            this.parentBuilder = parentBuilder;
+         }
+
+         public Builder nextRule() {
+            this.parentBuilder.addRule(build());
+            return new Builder(parentBuilder);
+         }
+
+         public Request.AddRulePayload.Builder endRule() {
+            this.parentBuilder.addRule(build());
+            return parentBuilder;
+         }
+
+         public Builder icmpCode(Integer icmpCode) {
+            this.icmpCode = icmpCode;
+            return this;
+         }
+
+         public Builder icmpType(Integer icmpType) {
+            this.icmpType = icmpType;
+            return this;
+         }
+
+         @Override
+         public Builder self() {
+            return this;
+         }
+
+         @Override
+         public RuleWithIcmp build() {
+            checkFields();
+            return RuleWithIcmp.create(icmpCode, icmpType, name, portRangeEnd, portRangeStart, protocol,
+                    sourceIp, sourceMac, targetIp);
+         }
+
+         @Override
+         protected void checkFields() {
+            super.checkFields();
+            checkIcmp();
+         }
+
+         private void checkIcmp() {
+            if (icmpCode != null)
+               checkArgument(icmpCode >= 1 && icmpCode <= 254, "ICMP code must be 1 to 254");
+            if (icmpType != null)
+               checkArgument(icmpType >= 1 && icmpType <= 254, "ICMP type must be 1 to 254");
+            if (icmpCode != null || icmpType != null)
+               checkArgument(protocol == Protocol.ICMP, "ICMP code and types can only be set for ICMP protocol");
+         }
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Nic.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Nic.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Nic.java
new file mode 100644
index 0000000..fc0de67
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Nic.java
@@ -0,0 +1,379 @@
+/*
+ * 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.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import autovalue.shaded.com.google.common.common.collect.Lists;
+
+import com.google.auto.value.AutoValue;
+
+import java.util.List;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.collect.ImmutableList;
+import static com.google.common.net.InetAddresses.isInetAddress;
+
+@AutoValue
+public abstract class Nic {
+
+   @Nullable
+   public abstract String id();
+
+   @Nullable
+   public abstract String name();
+
+   @Nullable
+   public abstract String dataCenterId();
+
+   public abstract int lanId();
+
+   public abstract boolean internetAccess();
+
+   @Nullable
+   public abstract String serverId();
+
+   @Nullable
+   public abstract List<String> ips();
+
+   @Nullable
+   public abstract String macAddress();
+
+   @Nullable
+   public abstract Firewall firewalls();
+
+   public abstract boolean dhcpActive();
+
+   @Nullable
+   public abstract String gatewayIp();
+
+   @Nullable
+   public abstract ProvisioningState state();
+
+   public static Nic create(String id, String name, String dataCenterId, int lanId, boolean internetAccess,
+           String serverId, List<String> ips, String macAddress, Firewall firewall, boolean dhcpActive,
+           String gatewayIp, ProvisioningState state) {
+      return new AutoValue_Nic(id, name, dataCenterId, lanId, internetAccess, serverId,
+              ips != null ? ImmutableList.copyOf(ips) : ImmutableList.<String>of(), macAddress,
+              firewall, dhcpActive, gatewayIp, state);
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromNic(this);
+   }
+
+   private static void checkIp(String ip) {
+      if (ip != null)
+         checkArgument(isInetAddress(ip), "Invalid IP");
+   }
+
+   private static void checkIps(List<String> ips) {
+      for (String ip : ips)
+         checkIp(ip);
+   }
+
+   public static class Builder {
+
+      public String id;
+
+      public String name;
+
+      public String dataCenterId;
+
+      public int lanId;
+
+      public boolean internetAccess;
+
+      public String serverId;
+
+      @Nullable
+      public List<String> ips;
+
+      public String macAddress;
+
+      public Firewall firewall;
+
+      public boolean dhcpActive;
+
+      public String gatewayIp;
+
+      public ProvisioningState state;
+
+      public Builder() {
+         this.ips = Lists.newArrayList();
+      }
+
+      public Builder id(String id) {
+         this.id = id;
+         return this;
+      }
+
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      public Builder dataCenterId(String dataCenterId) {
+         this.dataCenterId = dataCenterId;
+         return this;
+      }
+
+      public Builder lanId(int lanId) {
+         this.lanId = lanId;
+         return this;
+      }
+
+      public Builder internetAccess(boolean internetAccess) {
+         this.internetAccess = internetAccess;
+         return this;
+      }
+
+      public Builder serverId(String serverId) {
+         this.serverId = serverId;
+         return this;
+      }
+
+      public Builder ips(List<String> ips) {
+         this.ips = ips;
+         return this;
+      }
+
+      public Builder ip(String ip) {
+         this.ips.add(ip);
+         return this;
+      }
+
+      public Builder macAddress(String macAddress) {
+         this.macAddress = macAddress;
+         return this;
+      }
+
+      public Builder dhcpActive(boolean dhcpActive) {
+         this.dhcpActive = dhcpActive;
+         return this;
+      }
+
+      public Builder gatewayIp(String gatewayIp) {
+         this.gatewayIp = gatewayIp;
+         return this;
+      }
+
+      public Builder state(ProvisioningState state) {
+         this.state = state;
+         return this;
+      }
+
+      public Builder firewall(Firewall firewall) {
+         this.firewall = firewall;
+         return this;
+      }
+
+      public Nic build() {
+         checkIps(ips);
+         return Nic.create(id, name, dataCenterId, lanId, internetAccess, serverId, ips,
+                 macAddress, firewall, dhcpActive, gatewayIp, state);
+      }
+
+      private Builder fromNic(Nic in) {
+         return this.id(in.id()).name(in.name()).lanId(in.lanId()).internetAccess(in.internetAccess())
+                 .serverId(in.serverId()).ips(in.ips()).macAddress(in.macAddress()).dhcpActive(in.dhcpActive())
+                 .gatewayIp(in.gatewayIp()).dataCenterId(dataCenterId);
+      }
+   }
+
+   public static final class Request {
+
+      public static CreatePayload.Builder creatingBuilder() {
+         return new CreatePayload.Builder();
+      }
+
+      public static UpdatePayload.Builder updatingBuilder() {
+         return new UpdatePayload.Builder();
+      }
+
+      public static SetInternetAccessPayload.Builder setInternetAccessBuilder() {
+         return new SetInternetAccessPayload.Builder();
+      }
+
+      @AutoValue
+      public abstract static class CreatePayload {
+
+         @Nullable
+         public abstract String ip();
+
+         @Nullable
+         public abstract String name();
+
+         @Nullable
+         public abstract Boolean dhcpActive();
+
+         public abstract String serverId();
+
+         public abstract int lanId();
+
+         public static CreatePayload create(String ip, String name, Boolean dhcpActive, String serverId, int lanId) {
+            return new AutoValue_Nic_Request_CreatePayload(ip, name, dhcpActive, serverId, lanId);
+         }
+
+         public static class Builder {
+
+            private String ip;
+            private String name;
+            private Boolean dhcpActive;
+            private String serverId;
+            private int lanId;
+
+            public Builder ip(String ip) {
+               this.ip = ip;
+               return this;
+            }
+
+            public Builder name(String name) {
+               this.name = name;
+               return this;
+            }
+
+            public Builder dhcpActive(Boolean dhcpActive) {
+               this.dhcpActive = dhcpActive;
+               return this;
+            }
+
+            public Builder serverId(String serverId) {
+               this.serverId = serverId;
+               return this;
+            }
+
+            public Builder lanId(int lanId) {
+               this.lanId = lanId;
+               return this;
+            }
+
+            public CreatePayload build() {
+               checkIp(ip);
+               return CreatePayload.create(ip, name, dhcpActive, serverId, lanId);
+            }
+
+         }
+
+      }
+
+      @AutoValue
+      public abstract static class UpdatePayload {
+
+         public abstract String id();
+
+         @Nullable
+         public abstract String ip();
+
+         @Nullable
+         public abstract String name();
+
+         @Nullable
+         public abstract Boolean dhcpActive();
+
+         public abstract int lanId();
+
+         public static UpdatePayload create(String id, String ip, String name, Boolean dhcpActive, int lanId) {
+            return new AutoValue_Nic_Request_UpdatePayload(id, ip, name, dhcpActive, lanId);
+         }
+
+         public static class Builder {
+
+            private String id;
+            private String ip;
+            private String name;
+            private Boolean dhcpActive;
+            private int lanId;
+
+            public Builder ip(String ip) {
+               this.ip = ip;
+               return this;
+            }
+
+            public Builder name(String name) {
+               this.name = name;
+               return this;
+            }
+
+            public Builder dhcpActive(Boolean dhcpActive) {
+               this.dhcpActive = dhcpActive;
+               return this;
+            }
+
+            public Builder lanId(int lanId) {
+               this.lanId = lanId;
+               return this;
+            }
+
+            public Builder id(String id) {
+               this.id = id;
+               return this;
+            }
+
+            public UpdatePayload build() {
+               checkIp(ip);
+               return UpdatePayload.create(id, ip, name, dhcpActive, lanId);
+            }
+         }
+      }
+
+      @AutoValue
+      public abstract static class SetInternetAccessPayload {
+
+         public abstract String dataCenterId();
+
+         public abstract int lanId();
+
+         public abstract boolean internetAccess();
+
+         public static SetInternetAccessPayload create(String dataCenterId, int lanId, boolean internetAccess) {
+            return new AutoValue_Nic_Request_SetInternetAccessPayload(dataCenterId, lanId, internetAccess);
+         }
+
+         public static class Builder {
+
+            public String dataCenterId;
+            public int lanId;
+            public boolean internetAccess;
+
+            public Builder dataCenterId(String dataCenterId) {
+               this.dataCenterId = dataCenterId;
+               return this;
+            }
+
+            public Builder lanId(int lanId) {
+               this.lanId = lanId;
+               return this;
+            }
+
+            public Builder internetAccess(boolean internetAccess) {
+               this.internetAccess = internetAccess;
+               return this;
+            }
+
+            public SetInternetAccessPayload build() {
+               return SetInternetAccessPayload.create(dataCenterId, lanId, internetAccess);
+            }
+         }
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Server.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Server.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Server.java
index 6149cfd..1074fcd 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Server.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Server.java
@@ -81,14 +81,17 @@ public abstract class Server implements ServerCommonProperties {
    @Nullable
    public abstract List<Storage> storages();
 
-//   public abstract List<Nic> nics();
+   @Nullable
+   public abstract List<Nic> nics();
+
    public static Server create(String id, String name, int cores, int ram, Boolean hasInternetAccess, ProvisioningState state,
            Status status, OsType osType, AvailabilityZone availabilityZone, Date creationTime, Date lastModificationTime,
-           List<Storage> storages, Boolean isCpuHotPlug, Boolean isRamHotPlug, Boolean isNicHotPlug, Boolean isNicHotUnPlug,
-           Boolean isDiscVirtioHotPlug, Boolean isDiscVirtioHotUnPlug) {
+           List<Storage> storages, List<Nic> nics, Boolean isCpuHotPlug, Boolean isRamHotPlug, Boolean isNicHotPlug,
+           Boolean isNicHotUnPlug, Boolean isDiscVirtioHotPlug, Boolean isDiscVirtioHotUnPlug) {
       return new AutoValue_Server(isCpuHotPlug, isRamHotPlug, isNicHotPlug, isNicHotUnPlug, isDiscVirtioHotPlug, isDiscVirtioHotUnPlug,
               cores, ram, id, name, hasInternetAccess, state, status, osType, availabilityZone, creationTime, lastModificationTime,
-              storages != null ? ImmutableList.copyOf(storages) : Lists.<Storage>newArrayList());
+              storages != null ? ImmutableList.copyOf(storages) : Lists.<Storage>newArrayList(),
+              nics != null ? ImmutableList.copyOf(nics) : Lists.<Nic>newArrayList());
 
    }
 
@@ -174,6 +177,7 @@ public abstract class Server implements ServerCommonProperties {
       private Date lastModificationTime;
       private Boolean hasInternetAccess;
       private List<Storage> storages;
+      private List<Nic> nics;
 
       public DescribingBuilder id(String id) {
          this.id = id;
@@ -220,18 +224,25 @@ public abstract class Server implements ServerCommonProperties {
          return this;
       }
 
+      public DescribingBuilder nics(List<Nic> nics) {
+         this.nics = nics;
+         return this;
+      }
+
       @Override
       public Server build() {
          return Server.create(id, name, cores, ram, hasInternetAccess, state, status, osType, zone, creationTime,
-                 lastModificationTime, storages, cpuHotPlug, ramHotPlug, nicHotPlug, nicHotUnPlug, discVirtioHotPlug, discVirtioHotUnPlug);
+                 lastModificationTime, storages, nics, cpuHotPlug, ramHotPlug, nicHotPlug, nicHotUnPlug,
+                 discVirtioHotPlug, discVirtioHotUnPlug);
       }
 
       private DescribingBuilder fromServer(Server in) {
          return this.id(in.id()).cores(in.cores()).creationTime(in.creationTime()).hasInternetAccess(in.hasInternetAccess())
-                 .isCpuHotPlug(in.isCpuHotPlug()).isDiscVirtioHotPlug(in.isDiscVirtioHotPlug()).isDiscVirtioHotUnPlug(in.isDiscVirtioHotUnPlug())
-                 .isNicHotPlug(in.isNicHotPlug()).isNicHotUnPlug(in.isNicHotUnPlug()).isRamHotPlug(in.isRamHotPlug())
-                 .lastModificationTime(in.lastModificationTime()).name(in.name()).osType(in.osType()).ram(in.ram()).state(in.state())
-                 .status(in.status()).storages(in.storages());
+                 .isCpuHotPlug(in.isCpuHotPlug()).isDiscVirtioHotPlug(in.isDiscVirtioHotPlug())
+                 .isDiscVirtioHotUnPlug(in.isDiscVirtioHotUnPlug()).isNicHotPlug(in.isNicHotPlug())
+                 .isNicHotUnPlug(in.isNicHotUnPlug()).isRamHotPlug(in.isRamHotPlug())
+                 .lastModificationTime(in.lastModificationTime()).name(in.name()).osType(in.osType()).ram(in.ram())
+                 .state(in.state()).status(in.status()).storages(in.storages()).nics(in.nics());
       }
 
       @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Storage.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Storage.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Storage.java
index 6dcaf25..827217b 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Storage.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/Storage.java
@@ -58,6 +58,7 @@ public abstract class Storage {
    @Nullable
    public abstract Date lastModificationTime();
 
+   @Nullable
    public abstract ProvisioningState state();
 
    @Nullable

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/internal/FirewallRuleCommonProperties.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/internal/FirewallRuleCommonProperties.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/internal/FirewallRuleCommonProperties.java
new file mode 100644
index 0000000..c607e38
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/internal/FirewallRuleCommonProperties.java
@@ -0,0 +1,44 @@
+/*
+ * 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.domain.internal;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.profitbricks.domain.Firewall;
+
+public interface FirewallRuleCommonProperties {
+
+   @Nullable
+   String name();
+
+   @Nullable
+   Integer portRangeEnd();
+
+   @Nullable
+   Integer portRangeStart();
+
+   @Nullable
+   Firewall.Protocol protocol();
+
+   @Nullable
+   String sourceIp();
+
+   @Nullable
+   String sourceMac();
+
+   @Nullable
+   String targetIp();
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/DataCenterApi.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/DataCenterApi.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/DataCenterApi.java
index a9c6143..f660730 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/DataCenterApi.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/DataCenterApi.java
@@ -58,7 +58,8 @@ public interface DataCenterApi {
 
    /**
     * @param identifier Data Center identifier
-    * @return Returns information about an existing virtual data center's state and configuration or <code>null</code> if it doesn't exist.
+    * @return Returns information about an existing virtual data center's state and configuration or <code>null</code>
+    * if it doesn't exist.
     */
    @POST
    @Named("datacenter:get")
@@ -68,8 +69,8 @@ public interface DataCenterApi {
    DataCenter getDataCenter(@PayloadParam("id") String identifier);
 
    /**
-    * This is a lightweight function for polling the current provisioning state of the Virtual Data Center. It is recommended to use this
-    * function for large Virtual Data Centers to query request results.
+    * This is a lightweight function for polling the current provisioning state of the Virtual Data Center. It is
+    * recommended to use this function for large Virtual Data Centers to query request results.
     * <p>
     * @param identifier Data Center identifier
     */
@@ -118,8 +119,9 @@ public interface DataCenterApi {
    DataCenter clearDataCenter(@PayloadParam("id") String identifier);
 
    /**
-    * Deletes an Virtual Data Center. If a previous request on the target data center is still in progress, the data center is going to be
-    * deleted after this request has been completed. Once a Data Center has been deleted, no further request can be performed on it.
+    * Deletes an Virtual Data Center. If a previous request on the target data center is still in progress, the data
+    * center is going to be deleted after this request has been completed. Once a Data Center has been deleted, no
+    * further request can be performed on it.
     * <p>
     * @param identifier Identifier of the virtual data center
     * @return Returns a boolean indicating whether delete operation was made

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/FirewallApi.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/FirewallApi.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/FirewallApi.java
new file mode 100644
index 0000000..f0aefb9
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/FirewallApi.java
@@ -0,0 +1,93 @@
+/*
+ * 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.features;
+
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks;
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.profitbricks.binder.firewall.AddFirewallRuleToNicRequestBinder;
+import org.jclouds.profitbricks.binder.firewall.FirewallBinder.ActivateFirewallRequestBinder;
+import org.jclouds.profitbricks.binder.firewall.FirewallBinder.DeactivateFirewallRequestBinder;
+import org.jclouds.profitbricks.binder.firewall.FirewallBinder.DeleteFirewallRequestBinder;
+import org.jclouds.profitbricks.binder.firewall.FirewallBinder.RemoveFirewallRuleRequestBinder;
+import org.jclouds.profitbricks.domain.Firewall;
+import org.jclouds.profitbricks.http.filters.ProfitBricksSoapMessageEnvelope;
+import org.jclouds.profitbricks.http.parser.firewall.FirewallListResponseHandler;
+import org.jclouds.profitbricks.http.parser.firewall.FirewallResponseHandler;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.rest.annotations.Fallback;
+
+@RequestFilters({BasicAuthentication.class, ProfitBricksSoapMessageEnvelope.class})
+@Consumes(MediaType.TEXT_XML)
+@Produces(MediaType.TEXT_XML)
+public interface FirewallApi {
+
+   @POST
+   @Named("firewall:get")
+   @Payload("<ws:getFirewall><firewallId>{id}</firewallId></ws:getFirewall>")
+   @XMLResponseParser(FirewallResponseHandler.class)
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   Firewall getFirewall(@PayloadParam("id") String identifier);
+
+   @POST
+   @Named("firewall:getall")
+   @Payload("<ws:getAllFirewalls/>")
+   @XMLResponseParser(FirewallListResponseHandler.class)
+   @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+   List<Firewall> getAllFirewalls();
+
+   @POST
+   @Named("firewall:addrule")
+   @MapBinder(AddFirewallRuleToNicRequestBinder.class)
+   @XMLResponseParser(FirewallResponseHandler.class)
+   Firewall addFirewallRuleToNic(@PayloadParam("firewall") Firewall.Request.AddRulePayload payload);
+
+   @POST
+   @Named("firewall:removerule")
+   @MapBinder(RemoveFirewallRuleRequestBinder.class)
+   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   boolean removeFirewallRules(@PayloadParam("ids") List<String> firewallRuleIds);
+
+   @POST
+   @Named("firewall:activate")
+   @MapBinder(ActivateFirewallRequestBinder.class)
+   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   boolean activateFirewall(@PayloadParam("ids") List<String> firewallIds);
+
+   @POST
+   @Named("firewall:activate")
+   @MapBinder(DeactivateFirewallRequestBinder.class)
+   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   boolean deactivateFirewall(@PayloadParam("ids") List<String> firewallIds);
+
+   @POST
+   @Named("firewall:activate")
+   @MapBinder(DeleteFirewallRequestBinder.class)
+   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   boolean deleteFirewall(@PayloadParam("ids") List<String> firewallIds);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/NicApi.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/NicApi.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/NicApi.java
new file mode 100644
index 0000000..57e425f
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/NicApi.java
@@ -0,0 +1,84 @@
+/*
+ * 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.features;
+
+import org.jclouds.Fallbacks;
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.profitbricks.binder.nic.CreateNicRequestBinder;
+import org.jclouds.profitbricks.binder.nic.SetInternetAccessBinder;
+import org.jclouds.profitbricks.binder.nic.UpdateNicRequestBinder;
+import org.jclouds.profitbricks.domain.Nic;
+import org.jclouds.profitbricks.http.filters.ProfitBricksSoapMessageEnvelope;
+import org.jclouds.profitbricks.http.parser.nic.NicListResponseHandler;
+import org.jclouds.profitbricks.http.parser.nic.NicResponseHandler;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.POST;
+import java.util.List;
+
+@RequestFilters({BasicAuthentication.class, ProfitBricksSoapMessageEnvelope.class})
+@Consumes(MediaType.TEXT_XML)
+@Produces(MediaType.TEXT_XML)
+public interface NicApi {
+
+   @POST
+   @Named("nics:getall")
+   @Payload("<ws:getAllNic/>")
+   @XMLResponseParser(NicListResponseHandler.class)
+   @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+   List<Nic> getAllNics();
+
+   @POST
+   @Named("nic:create")
+   @MapBinder(CreateNicRequestBinder.class)
+   @XMLResponseParser(NicResponseHandler.class)
+   Nic createNic(@PayloadParam("nic") Nic.Request.CreatePayload payload);
+
+   @POST
+   @Named("nic:get")
+   @Payload("<ws:getNic><nicId>{id}</nicId></ws:getNic>")
+   @XMLResponseParser(NicResponseHandler.class)
+   @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+   Nic getNic(@PayloadParam("id") String identifier);
+
+   @POST
+   @Named("nic:update")
+   @MapBinder(UpdateNicRequestBinder.class)
+   @XMLResponseParser(NicResponseHandler.class)
+   Nic updateNic(@PayloadParam("nic") Nic.Request.UpdatePayload payload);
+
+   @POST
+   @Named("nic:setInternetAccess")
+   @MapBinder(SetInternetAccessBinder.class)
+   @XMLResponseParser(NicResponseHandler.class)
+   Nic setInternetAccess(@PayloadParam("nic") Nic.Request.SetInternetAccessPayload payload);
+
+   @POST
+   @Named("nic:delete")
+   @Payload("<ws:deleteNic><nicId>{id}</nicId></ws:deleteNic>")
+   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   boolean deleteNic(@PayloadParam("id") String id);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/ServerApi.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/ServerApi.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/ServerApi.java
index 34445da..344797d 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/ServerApi.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/ServerApi.java
@@ -45,7 +45,8 @@ import org.jclouds.rest.annotations.XMLResponseParser;
 public interface ServerApi {
 
    /**
-    * @return Returns information about all virtual server, such as configuration, provisioning status, power status, etc.
+    * @return Returns information about all virtual server, such as configuration, provisioning status, power status,
+    * etc.
     */
    @POST
    @Named("server:getall")
@@ -88,12 +89,13 @@ public interface ServerApi {
     * <ul>
     * <li>Server will be forcefully powered off. Any unsaved data may be lost! </li>
     * <li>Billing for this server will be stopped </li>
-    * <li>When restarting the server a new public IP gets assigned, alternatively, you can reserve IP addresses, see reservation of public
-    * IP blocks</li>
+    * <li>When restarting the server a new public IP gets assigned, alternatively, you can reserve IP addresses, see
+    * reservation of public IP blocks</li>
     * </ul>
     *
-    * A graceful stop of a server is not possible through the ProfitBricks API. We recommend to access and execute the command on the
-    * virtual server directly. Once the server was shutdown you still can use the "stopServer" method that will stop billing.
+    * A graceful stop of a server is not possible through the ProfitBricks API. We recommend to access and execute the
+    * command on the virtual server directly. Once the server was shutdown you still can use the "stopServer" method
+    * that will stop billing.
     *
     * @param id Identifier of the target virtual server
     * @return Identifier of current request
@@ -112,8 +114,8 @@ public interface ServerApi {
     * </ul>
     * <b>Graceful REBOOT</b>
     *
-    * A graceful reboot of a server is not possible through the ProfitBricks API. We recommend to access and execute the command on the
-    * virtual server directly.
+    * A graceful reboot of a server is not possible through the ProfitBricks API. We recommend to access and execute the
+    * command on the virtual server directly.
     *
     * @param id Identifier of the target virtual server
     * @return Identifier of current request
@@ -125,8 +127,8 @@ public interface ServerApi {
    String resetServer(@PayloadParam("id") String id);
 
    /**
-    * Creates a Virtual Server within an existing data center. Parameters can be specified to set up a boot device and connect the server to
-    * an existing LAN or the Internet.
+    * Creates a Virtual Server within an existing data center. Parameters can be specified to set up a boot device and
+    * connect the server to an existing LAN or the Internet.
     *
     * @param payload Payload
     * @return serverId of the created server

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/StorageApi.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/StorageApi.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/StorageApi.java
index f5d3577..0589af6 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/StorageApi.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/features/StorageApi.java
@@ -71,8 +71,8 @@ public interface StorageApi {
    Storage getStorage(@PayloadParam("id") String id);
 
    /**
-    * Creates a virtual storage within an existing virtual data center. Additional parameters can be specified, e.g. for assigning a HDD
-    * image to the storage.
+    * Creates a virtual storage within an existing virtual data center. Additional parameters can be specified, e.g. for
+    * assigning a HDD image to the storage.
     *
     * @param payload Payload
     * @return storageId of the created storage
@@ -84,9 +84,10 @@ public interface StorageApi {
    String createStorage(@PayloadParam("storage") Storage.Request.CreatePayload payload);
 
    /**
-    * Updates parameters of an existing virtual storage device. It is possible to increase the storage size without reboot of an already
-    * provisioned storage. The additional capacity is not added to any partition. You have to partition the storage afterwards. Vice versa,
-    * it is not possible to decrease the storage size of an already provisioned storage.
+    * Updates parameters of an existing virtual storage device. It is possible to increase the storage size without
+    * reboot of an already provisioned storage. The additional capacity is not added to any partition. You have to
+    * partition the storage afterwards. Vice versa, it is not possible to decrease the storage size of an already
+    * provisioned storage.
     *
     * @param payload Payload
     * @return Identifier of current request

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java
index b818d3d..00ca238 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java
@@ -64,10 +64,10 @@ public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl
 
    @Inject
    ResponseStatusFromPayloadHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
-	   DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
-	   DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
-	   @Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI,
-	   ParseSax<ServiceFault> faultHandler) {
+           DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
+           DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
+           @Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI,
+           ParseSax<ServiceFault> faultHandler) {
       super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, untrustedSSLContextProvider, proxyForURI);
       this.faultHandler = faultHandler;
    }
@@ -78,39 +78,39 @@ public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl
       HttpResponse.Builder<?> responseBuilder = originalResponse.toBuilder();
 
       if (hasServerError(originalResponse) && hasPayload(originalResponse)) {
-	 // As we need to read the response body to determine if there are errors, but we may need to process the body
-	 // again later in the response parsers if everything is OK, we buffer the body into an InputStream we can reset
-	 InputStream in = null;
-	 InputStream originalInputStream = originalResponse.getPayload().openStream();
-
-	 if (originalInputStream instanceof ByteArrayInputStream)
-	    in = originalInputStream;
-	 else
-	    try {
-	       in = new ByteArrayInputStream(ByteStreams.toByteArray(originalInputStream));
-	    } finally {
-	       closeQuietly(originalInputStream);
-	    }
-	 try {
-	    if (isSoapPayload(in)) {
-	       ServiceFault fault = faultHandler.parse(in);
-	       if (fault != null)
-		  responseBuilder
-			  .statusCode(fault.httpCode())
-			  .message(fault.message());
-	    }
-	 } catch (Exception ex) {
-	    // ignore
-	 } finally {
-	    // Reset the input stream and set the payload, so it can be read again
-	    // by the response and error parsers
-	    if (in != null) {
-	       in.reset();
-	       Payload payload = Payloads.newInputStreamPayload(in);
-	       contentMetadataCodec.fromHeaders(payload.getContentMetadata(), originalResponse.getHeaders());
-	       responseBuilder.payload(payload);
-	    }
-	 }
+         // As we need to read the response body to determine if there are errors, but we may need to process the body
+         // again later in the response parsers if everything is OK, we buffer the body into an InputStream we can reset
+         InputStream in = null;
+         InputStream originalInputStream = originalResponse.getPayload().openStream();
+
+         if (originalInputStream instanceof ByteArrayInputStream)
+            in = originalInputStream;
+         else
+            try {
+               in = new ByteArrayInputStream(ByteStreams.toByteArray(originalInputStream));
+            } finally {
+               closeQuietly(originalInputStream);
+            }
+         try {
+            if (isSoapPayload(in)) {
+               ServiceFault fault = faultHandler.parse(in);
+               if (fault != null)
+                  responseBuilder
+                          .statusCode(fault.httpCode())
+                          .message(fault.message());
+            }
+         } catch (Exception ex) {
+            // ignore
+         } finally {
+            // Reset the input stream and set the payload, so it can be read again
+            // by the response and error parsers
+            if (in != null) {
+               in.reset();
+               Payload payload = Payloads.newInputStreamPayload(in);
+               contentMetadataCodec.fromHeaders(payload.getContentMetadata(), originalResponse.getHeaders());
+               responseBuilder.payload(payload);
+            }
+         }
       }
 
       return responseBuilder.build();
@@ -131,7 +131,7 @@ public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl
 
       is.read(bytes, 0, size);
       for (int i = 0; i < size;)
-	 chars[i] = (char) (bytes[i++] & 0xff);
+         chars[i] = (char) (bytes[i++] & 0xff);
 
       is.reset(); // throws premature end of file w/o this
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/BaseProfitBricksResponseHandler.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/BaseProfitBricksResponseHandler.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/BaseProfitBricksResponseHandler.java
index 6a9933f..3520b37 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/BaseProfitBricksResponseHandler.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/BaseProfitBricksResponseHandler.java
@@ -56,6 +56,10 @@ public abstract class BaseProfitBricksResponseHandler<T> extends ParseSax.Handle
       strBuilder.setLength(0);
    }
 
+   public void reset() {
+
+   }
+
    @Override
    public abstract void endElement(String uri, String localName, String qName) throws SAXException;
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/datacenter/DataCenterInfoResponseHandler.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/datacenter/DataCenterInfoResponseHandler.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/datacenter/DataCenterInfoResponseHandler.java
index d44c880..3e833e5 100644
--- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/datacenter/DataCenterInfoResponseHandler.java
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/datacenter/DataCenterInfoResponseHandler.java
@@ -16,37 +16,29 @@
  */
 package org.jclouds.profitbricks.http.parser.datacenter;
 
-import java.util.List;
-
 import org.jclouds.profitbricks.domain.DataCenter;
 import org.jclouds.profitbricks.domain.Location;
 import org.jclouds.profitbricks.domain.ProvisioningState;
-import org.jclouds.profitbricks.domain.Server;
-import org.jclouds.profitbricks.domain.Storage;
-import org.jclouds.profitbricks.http.parser.server.ServerInfoResponseHandler;
-import org.jclouds.profitbricks.http.parser.storage.StorageInfoResponseHandler;
+import org.jclouds.profitbricks.http.parser.server.ServerListResponseHandler;
+import org.jclouds.profitbricks.http.parser.storage.StorageListResponseHandler;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
-import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 
 public class DataCenterInfoResponseHandler extends BaseDataCenterResponseHandler<DataCenter> {
 
-   private final ServerInfoResponseHandler serverInfoResponseHandler;
-   private final StorageInfoResponseHandler storageInfoResponseHandler;
-
-   private final List<Server> servers = Lists.newArrayList();
-   private final List<Storage> storages = Lists.newArrayList();
+   private final ServerListResponseHandler serverListResponseHandler;
+   private final StorageListResponseHandler storageListResponseHandler;
 
    private boolean done = false;
    private boolean useServerParser = false;
    private boolean useStorageParser = false;
 
    @Inject
-   DataCenterInfoResponseHandler(ServerInfoResponseHandler serverInfoResponseHandler, StorageInfoResponseHandler storageInforResponseHandler) {
-      this.serverInfoResponseHandler = serverInfoResponseHandler;
-      this.storageInfoResponseHandler = storageInforResponseHandler;
+   DataCenterInfoResponseHandler(ServerListResponseHandler serverListResponseHandler, StorageListResponseHandler storageListResponseHandler) {
+      this.serverListResponseHandler = serverListResponseHandler;
+      this.storageListResponseHandler = storageListResponseHandler;
    }
 
    @Override
@@ -55,6 +47,13 @@ public class DataCenterInfoResponseHandler extends BaseDataCenterResponseHandler
          useServerParser = true;
       else if ("storages".equals(qName))
          useStorageParser = true;
+
+      if (useServerParser)
+         serverListResponseHandler.startElement(uri, localName, qName, attributes);
+      else if (useStorageParser)
+         storageListResponseHandler.startElement(uri, localName, qName, attributes);
+      else
+         super.startElement(uri, localName, qName, attributes);
    }
 
    @Override
@@ -71,9 +70,9 @@ public class DataCenterInfoResponseHandler extends BaseDataCenterResponseHandler
    @Override
    public void characters(char[] ch, int start, int length) {
       if (useServerParser)
-         serverInfoResponseHandler.characters(ch, start, length);
+         serverListResponseHandler.characters(ch, start, length);
       else if (useStorageParser)
-         storageInfoResponseHandler.characters(ch, start, length);
+         storageListResponseHandler.characters(ch, start, length);
       else
          super.characters(ch, start, length);
    }
@@ -83,27 +82,24 @@ public class DataCenterInfoResponseHandler extends BaseDataCenterResponseHandler
       if (done)
          return;
 
-      if ("servers".equals(qName)) {
-         useServerParser = false;
-         servers.add(serverInfoResponseHandler.getResult());
-      } else if ("storages".equals(qName)) {
-         useStorageParser = false;
-         storages.add(storageInfoResponseHandler.getResult());
-      }
-
       if (useServerParser)
-         serverInfoResponseHandler.endElement(uri, localName, qName);
+         serverListResponseHandler.endElement(uri, localName, qName);
       else if (useStorageParser)
-         storageInfoResponseHandler.endElement(uri, localName, qName);
+         storageListResponseHandler.endElement(uri, localName, qName);
       else {
          setPropertyOnEndTag(qName);
          if ("return".equals(qName)) {
             done = true;
-            builder.servers(servers);
-            builder.storages(storages);
+            builder.servers(serverListResponseHandler.getResult());
+            builder.storages(storageListResponseHandler.getResult());
          }
          clearTextBuffer();
       }
+
+      if ("servers".equals(qName))
+         useServerParser = false;
+      else if ("storages".equals(qName))
+         useStorageParser = false;
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/firewall/BaseFirewallResponseHandler.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/firewall/BaseFirewallResponseHandler.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/firewall/BaseFirewallResponseHandler.java
new file mode 100644
index 0000000..310156b
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/firewall/BaseFirewallResponseHandler.java
@@ -0,0 +1,69 @@
+/*
+ * 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.http.parser.firewall;
+
+import com.google.inject.Inject;
+
+import org.jclouds.profitbricks.domain.Firewall;
+import org.jclouds.profitbricks.domain.ProvisioningState;
+import org.jclouds.profitbricks.http.parser.BaseProfitBricksResponseHandler;
+import org.jclouds.profitbricks.http.parser.firewall.rule.FirewallRuleListResponseHandler;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+public abstract class BaseFirewallResponseHandler<T> extends BaseProfitBricksResponseHandler<T> {
+
+   protected final FirewallRuleListResponseHandler firewallRuleListResponseHandler;
+
+   protected boolean useFirewallRuleParser = false;
+   protected Firewall.Builder builder;
+
+   @Inject
+   BaseFirewallResponseHandler(FirewallRuleListResponseHandler firewallRuleListResponseHandler) {
+      this.builder = Firewall.builder();
+      this.firewallRuleListResponseHandler = firewallRuleListResponseHandler;
+   }
+
+   @Override
+   public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+      if ("firewallRules".equals(qName))
+         useFirewallRuleParser = true;
+
+      if (useFirewallRuleParser)
+         firewallRuleListResponseHandler.startElement(uri, localName, qName, attributes);
+   }
+
+   @Override
+   public void characters(char[] ch, int start, int length) {
+      if (useFirewallRuleParser)
+         firewallRuleListResponseHandler.characters(ch, start, length);
+      else
+         super.characters(ch, start, length);
+   }
+
+   @Override
+   protected void setPropertyOnEndTag(String qName) {
+      if ("firewallId".equals(qName))
+         builder.id(textToStringValue());
+      else if ("active".equals(qName))
+         builder.active(textToBooleanValue());
+      else if ("nicId".equals(qName))
+         builder.nicId(textToStringValue());
+      else if ("provisioningState".equals(qName))
+         builder.state(ProvisioningState.fromValue(textToStringValue()));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/de2e5e01/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/firewall/FirewallListResponseHandler.java
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/firewall/FirewallListResponseHandler.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/firewall/FirewallListResponseHandler.java
new file mode 100644
index 0000000..6d8b292
--- /dev/null
+++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/firewall/FirewallListResponseHandler.java
@@ -0,0 +1,64 @@
+/*
+ * 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.http.parser.firewall;
+
+import autovalue.shaded.com.google.common.common.collect.Lists;
+
+import com.google.inject.Inject;
+
+import java.util.List;
+
+import org.jclouds.profitbricks.domain.Firewall;
+import org.jclouds.profitbricks.http.parser.firewall.rule.FirewallRuleListResponseHandler;
+import org.xml.sax.SAXException;
+
+public class FirewallListResponseHandler extends BaseFirewallResponseHandler<List<Firewall>> {
+
+   private final List<Firewall> firewalls;
+
+   @Inject
+   FirewallListResponseHandler(FirewallRuleListResponseHandler firewallRuleListResponseHandler) {
+      super(firewallRuleListResponseHandler);
+      this.firewalls = Lists.newArrayList();
+   }
+
+   @Override
+   public void endElement(String uri, String localName, String qName) throws SAXException {
+      if (useFirewallRuleParser)
+         firewallRuleListResponseHandler.endElement(uri, localName, qName);
+      else {
+         setPropertyOnEndTag(qName);
+         if ("return".equals(qName)) {
+            firewalls.add(builder
+                    .rules(firewallRuleListResponseHandler.getResult())
+                    .build());
+            firewallRuleListResponseHandler.reset();
+            builder = Firewall.builder();
+         }
+         clearTextBuffer();
+      }
+
+      if ("firewallRules".equals(qName))
+         useFirewallRuleParser = false;
+   }
+
+   @Override
+   public List<Firewall> getResult() {
+      return firewalls;
+   }
+
+}