oneandone-compue-api

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

Branch: refs/heads/master
Commit: eeaa3c6689d2f11e4367d1df051d34ee75d41ab9
Parents: 4d80bd7
Author: alibazlamit <ali@ali-G751JT>
Authored: Fri Feb 24 02:49:33 2017 +0100
Committer: Ignasi Barrera <[email protected]>
Committed: Fri Mar 3 11:54:27 2017 +0100

----------------------------------------------------------------------
 oneandone/pom.xml                               |  16 +-
 .../jclouds/oneandone/rest/OneAndOneApi.java    |  12 +-
 .../oneandone/rest/OneAndOneApiMetadata.java    |   5 +
 .../rest/OneAndOneProviderMetadata.java         |  19 +-
 .../compute/OneandoneComputeServiceAdapter.java | 292 +++++++++++++++++++
 .../OneAndOneComputeServiceContextModule.java   | 116 ++++++++
 .../config/OneAndOneRateLimitModule.java        |  30 ++
 .../compute/function/DataCenterToLocation.java  |  48 +++
 .../function/HardwareFlavourToHardware.java     |  64 ++++
 .../rest/compute/function/HddToVolume.java      |  40 +++
 .../compute/function/ServerToNodeMetadata.java  | 188 ++++++++++++
 .../function/SingleServerApplianceToImage.java  |  95 ++++++
 .../rest/compute/strategy/CleanupResources.java |  74 +++++
 .../rest/config/OneAndOneConstants.java         |  52 ----
 .../rest/config/OneAndOneHttpApiModule.java     |  37 +--
 .../rest/config/OneAndOneProperties.java        |   5 +-
 .../oneandone/rest/domain/DataCenter.java       |  18 +-
 .../jclouds/oneandone/rest/domain/Hardware.java |  10 +-
 .../jclouds/oneandone/rest/domain/Image.java    |   9 +-
 .../jclouds/oneandone/rest/domain/Server.java   |  10 +-
 .../oneandone/rest/domain/ServerAppliance.java  |  77 +++++
 .../rest/domain/SingleServerAppliance.java      | 154 ++++++++++
 .../jclouds/oneandone/rest/domain/Types.java    |  18 ++
 .../OneAndOneRateLimitExceededException.java    |  75 +++++
 .../oneandone/rest/features/DataCenterApi.java  |  55 ++++
 .../rest/features/ServerApplianceApi.java       |  91 ++++++
 .../rest/filters/AuthenticateRequest.java       |   4 +-
 .../handlers/OneAndOneHttpErrorHandler.java     |  21 +-
 .../OneAndOneRateLimitRetryHandler.java         |  46 +++
 .../jclouds/oneandone/rest/util/Passwords.java  |  64 ++++
 .../rest/util/ServerApplianceParser.java        | 110 +++++++
 .../OneAndOneComputeServiceLiveTest.java        | 111 +++++++
 .../OneAndOneTemplateBuilderLiveTest.java       |  35 +++
 .../function/CustomHardwareToHardwareTest.java  |  81 +++++
 .../function/HardwareFlavourToHardwareTest.java |  83 ++++++
 .../rest/compute/function/HddToVolumeTest.java  |  52 ++++
 .../function/ServerToNodeMetadataTest.java      | 195 +++++++++++++
 .../SingleServerApplianceToImageTest.java       |  65 +++++
 .../rest/features/DataCenterApiLiveTest.java    |  68 +++++
 .../rest/features/DataCenterApiMockTest.java    | 115 ++++++++
 .../rest/features/ServerApiMockTest.java        |   1 +
 .../features/ServerApplianceApiLiveTest.java    |  61 ++++
 .../features/ServerApplianceApiMockTest.java    | 116 ++++++++
 .../rest/internal/BaseOneAndOneApiMockTest.java |   2 +-
 .../rest/internal/BaseOneAndOneLiveTest.java    |  23 +-
 .../src/test/resources/compute/hardware.json    |  15 +
 oneandone/src/test/resources/compute/image.json |  30 ++
 .../src/test/resources/compute/server.json      |  48 +++
 .../src/test/resources/compute/volume.json      |   5 +
 .../src/test/resources/datacenter/get.json      |   6 +
 .../src/test/resources/datacenter/list.json     |  22 ++
 .../test/resources/datacenter/list.options.json |  22 ++
 .../src/test/resources/serverappliance/get.json |  30 ++
 .../test/resources/serverappliance/list.json    |  29 ++
 .../resources/serverappliance/list.options.json |  86 ++++++
 55 files changed, 3025 insertions(+), 131 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/pom.xml
----------------------------------------------------------------------
diff --git a/oneandone/pom.xml b/oneandone/pom.xml
index 6454385..4ebc4d7 100644
--- a/oneandone/pom.xml
+++ b/oneandone/pom.xml
@@ -33,7 +33,8 @@
     
     <properties>
         
<test.oneandone.endpoint>https://cloudpanel-api.1and1.com/v1/</test.oneandone.endpoint>
-        <test.oneandone.identity>FIXME</test.oneandone.identity>
+        <test.oneandone.identity>token</test.oneandone.identity>
+        <test.oneandone.credential>token</test.oneandone.credential>
         <test.oneandone.api-version>1.0</test.oneandone.api-version>
         
<jclouds.osgi.export>org.jclouds.oneandone*;version="${project.version}"</jclouds.osgi.export>
         <jclouds.osgi.import>
@@ -50,6 +51,11 @@
             <version>${jclouds.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
             <groupId>com.google.auto.service</groupId>
             <artifactId>auto-service</artifactId>
             <scope>provided</scope>
@@ -73,6 +79,13 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${jclouds.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.jclouds.driver</groupId>
             <artifactId>jclouds-sshj</artifactId>
             <version>${jclouds.version}</version>
@@ -129,6 +142,7 @@
                                     <systemPropertyVariables>
                                         
<test.oneandone.endpoint>${test.oneandone.endpoint}</test.oneandone.endpoint>
                                         
<test.oneandone.identity>${test.oneandone.identity}</test.oneandone.identity>
+                                        
<test.oneandone.credential>${test.oneandone.credential}</test.oneandone.credential>
                                         
<test.oneandone.api-version>${test.oneandone.api-version}</test.oneandone.api-version>
                                     </systemPropertyVariables>
                                 </configuration>

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApi.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApi.java 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApi.java
index 77352d4..388e5f9 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApi.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApi.java
@@ -17,6 +17,7 @@
 package org.apache.jclouds.oneandone.rest;
 
 import java.io.Closeable;
+import org.apache.jclouds.oneandone.rest.features.DataCenterApi;
 import org.apache.jclouds.oneandone.rest.features.FirewallPolicyApi;
 import org.apache.jclouds.oneandone.rest.features.ImageApi;
 import org.apache.jclouds.oneandone.rest.features.LoadBalancerApi;
@@ -25,6 +26,7 @@ import 
org.apache.jclouds.oneandone.rest.features.MonitoringPolicyApi;
 import org.apache.jclouds.oneandone.rest.features.PrivateNetworkApi;
 import org.apache.jclouds.oneandone.rest.features.PublicIpApi;
 import org.apache.jclouds.oneandone.rest.features.ServerApi;
+import org.apache.jclouds.oneandone.rest.features.ServerApplianceApi;
 import org.apache.jclouds.oneandone.rest.features.SharedStorageApi;
 import org.apache.jclouds.oneandone.rest.features.VpnApi;
 import org.jclouds.rest.annotations.Delegate;
@@ -52,12 +54,18 @@ public interface OneAndOneApi extends Closeable {
    @Delegate
    PrivateNetworkApi privateNetworkApi();
 
-    @Delegate
-    VpnApi vpnApi();
+   @Delegate
+   VpnApi vpnApi();
 
    @Delegate
    MonitoringCenterApi monitoringCenterApi();
 
    @Delegate
    MonitoringPolicyApi monitoringPolicyApi();
+
+   @Delegate
+   DataCenterApi dataCenterApi();
+
+   @Delegate
+   ServerApplianceApi serverApplianceApi();
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApiMetadata.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApiMetadata.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApiMetadata.java
index 4fa0416..99e6ba2 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApiMetadata.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneApiMetadata.java
@@ -20,7 +20,9 @@ import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
 import java.net.URI;
 import java.util.Properties;
+import 
org.apache.jclouds.oneandone.rest.compute.config.OneAndOneComputeServiceContextModule;
 import org.apache.jclouds.oneandone.rest.config.OneAndOneHttpApiModule;
+import org.jclouds.compute.ComputeServiceContext;
 import org.jclouds.http.okhttp.config.OkHttpCommandExecutorServiceModule;
 import org.jclouds.rest.internal.BaseHttpApiMetadata;
 
@@ -50,12 +52,15 @@ public class OneAndOneApiMetadata extends 
BaseHttpApiMetadata<OneAndOneApi> {
          id("oneandone")
                  .name("OneAndOne REST API")
                  .identityName("API Username")
+                 .credentialName("token")
                  
.documentation(URI.create("https://cloudpanel-api.1and1.com/documentation/1and1/v1/en/documentation.html";))
                  .defaultEndpoint("https://cloudpanel-api.1and1.com/v1";)
+                 .view(ComputeServiceContext.class)
                  .defaultProperties(OneAndOneApiMetadata.defaultProperties())
                  .defaultModules(ImmutableSet.<Class<? extends 
Module>>builder()
                          .add(OkHttpCommandExecutorServiceModule.class)
                          .add(OneAndOneHttpApiModule.class)
+                         .add(OneAndOneComputeServiceContextModule.class)
                          .build());
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneProviderMetadata.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneProviderMetadata.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneProviderMetadata.java
index 176f994..5b4fd07 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneProviderMetadata.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/OneAndOneProviderMetadata.java
@@ -19,11 +19,12 @@ package org.apache.jclouds.oneandone.rest;
 import com.google.auto.service.AutoService;
 import java.net.URI;
 import java.util.Properties;
-import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_MAX_PERIOD;
-import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_PERIOD;
 import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_TIMEOUT;
 import static org.jclouds.Constants.PROPERTY_CONNECTION_TIMEOUT;
+import static org.jclouds.Constants.PROPERTY_MAX_RATE_LIMIT_WAIT;
 import static org.jclouds.Constants.PROPERTY_SO_TIMEOUT;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.POLL_INITIAL_PERIOD;
+import static 
org.jclouds.compute.config.ComputeServiceProperties.POLL_MAX_PERIOD;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.providers.internal.BaseProviderMetadata;
 
@@ -49,12 +50,18 @@ public class OneAndOneProviderMetadata extends 
BaseProviderMetadata {
 
    public static Properties defaultProperties() {
       Properties properties = OneAndOneApiMetadata.defaultProperties();
+
+//      properties.setProperty(PROPERTY_REGIONS, "de,us,es,gb");
+      properties.put("jclouds.ssh.max-retries", "7");
+      properties.put("jclouds.ssh.retry-auth", "true");
+
       long defaultTimeout = 60L * 60L; // 1 hour
       properties.put(POLL_TIMEOUT, defaultTimeout);
-      properties.put(POLL_PERIOD, 1L);
-      properties.put(POLL_MAX_PERIOD, 1L * 9L);
-      properties.put(PROPERTY_SO_TIMEOUT, 60000 * 5);
+      properties.put(POLL_INITIAL_PERIOD, 5L * 10);
+      properties.put(POLL_MAX_PERIOD, 7L * 10L);
+      properties.put(PROPERTY_SO_TIMEOUT, 6000 * 5);
       properties.put(PROPERTY_CONNECTION_TIMEOUT, 60000 * 5);
+      properties.put(PROPERTY_MAX_RATE_LIMIT_WAIT, 330000);
 
       return properties;
    }
@@ -67,7 +74,7 @@ public class OneAndOneProviderMetadata extends 
BaseProviderMetadata {
                  .apiMetadata(new OneAndOneApiMetadata())
                  .homepage(URI.create("https://cloudpanel-api.1and1.com";))
                  .console(URI.create("https://account.1and1.com";))
-                 .endpoint("https://cloudpanel-api.1and1.com/v1";)
+                 .endpoint("https://cloudpanel-api.1and1.com/v1/";)
                  
.defaultProperties(OneAndOneProviderMetadata.defaultProperties());
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/OneandoneComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/OneandoneComputeServiceAdapter.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/OneandoneComputeServiceAdapter.java
new file mode 100644
index 0000000..fe6d521
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/OneandoneComputeServiceAdapter.java
@@ -0,0 +1,292 @@
+/*
+ * 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.oneandone.rest.compute;
+
+import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Predicate;
+import static com.google.common.base.Strings.isNullOrEmpty;
+import com.google.common.base.Throwables;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import com.google.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Resource;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import org.apache.jclouds.oneandone.rest.OneAndOneApi;
+import org.apache.jclouds.oneandone.rest.compute.strategy.CleanupResources;
+import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_PREDICATE_SERVER;
+import org.apache.jclouds.oneandone.rest.domain.DataCenter;
+import org.apache.jclouds.oneandone.rest.domain.FirewallPolicy;
+import org.apache.jclouds.oneandone.rest.domain.HardwareFlavour;
+import org.apache.jclouds.oneandone.rest.domain.Hdd;
+import org.apache.jclouds.oneandone.rest.domain.Server;
+import org.apache.jclouds.oneandone.rest.domain.ServerAppliance;
+import org.apache.jclouds.oneandone.rest.domain.SingleServerAppliance;
+import org.apache.jclouds.oneandone.rest.domain.Types;
+import org.apache.jclouds.oneandone.rest.domain.options.GenericQueryOptions;
+import org.apache.jclouds.oneandone.rest.util.Passwords;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.util.ComputeServiceUtils;
+import static 
org.jclouds.compute.util.ComputeServiceUtils.getPortRangesFromList;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.logging.Logger;
+import org.jclouds.rest.ResourceNotFoundException;
+
+@Singleton
+public class OneandoneComputeServiceAdapter implements 
ComputeServiceAdapter<Server, HardwareFlavour, SingleServerAppliance, 
DataCenter> {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final CleanupResources cleanupResources;
+   private final OneAndOneApi api;
+   private final Predicate<Server> waitServerUntilAvailable;
+
+   @Inject
+   OneandoneComputeServiceAdapter(OneAndOneApi api, CleanupResources 
cleanupResources,
+           @Named(POLL_PREDICATE_SERVER) Predicate<Server> 
waitServerUntilAvailable) {
+      this.api = api;
+      this.cleanupResources = cleanupResources;
+      this.waitServerUntilAvailable = waitServerUntilAvailable;
+   }
+
+   @Override
+   public NodeAndInitialCredentials<Server> 
createNodeWithGroupEncodedIntoName(String group, String name, Template 
template) {
+
+      final String dataCenterId = template.getLocation().getId();
+      Hardware hardware = template.getHardware();
+      TemplateOptions options = template.getOptions();
+      Server updateServer = null;
+
+      final String loginUser = isNullOrEmpty(options.getLoginUser()) ? "root" 
: options.getLoginUser();
+      final String password = options.hasLoginPassword() ? 
options.getLoginPassword() : Passwords.generate();
+      final String privateKey = options.hasLoginPrivateKey() ? 
options.getPrivateKey() : null;
+      final org.jclouds.compute.domain.Image image = template.getImage();
+      final int[] inboundPorts = template.getOptions().getInboundPorts();
+
+      //prepare hdds to provision
+      List<? extends Volume> volumes = hardware.getVolumes();
+      List<Hdd.CreateHdd> hdds = new ArrayList<Hdd.CreateHdd>();
+
+      int i = 1;
+      for (final Volume volume : volumes) {
+         try {
+            //check if the bootable device has enough size to run the 
appliance(image).
+            float minHddSize = volume.getSize();
+            if (volume.isBootDevice()) {
+               SingleServerAppliance appliance = 
api.serverApplianceApi().get(image.getId());
+               if (appliance.minHddSize() > volume.getSize()) {
+                  minHddSize = appliance.minHddSize();
+               }
+            }
+            Hdd.CreateHdd hdd = Hdd.CreateHdd.create(minHddSize, 
volume.isBootDevice());
+            hdds.add(hdd);
+         } catch (Exception ex) {
+            throw Throwables.propagate(ex);
+
+         }
+      }
+
+      // provision server
+      Server server = null;
+      Double cores = ComputeServiceUtils.getCores(hardware);
+      Double ram = (double) hardware.getRam();
+      if (ram < 1024) {
+         ram = 0.5;
+      } else {
+         ram = ram / 1024;
+      }
+
+      try {
+         List<? extends Processor> processors = hardware.getProcessors();
+         org.apache.jclouds.oneandone.rest.domain.Hardware.CreateHardware 
hardwareRequest
+                 = 
org.apache.jclouds.oneandone.rest.domain.Hardware.CreateHardware.create(cores, 
1, ram, hdds);
+         final Server.CreateServer serverRequest = 
Server.CreateServer.builder()
+                 .name(name)
+                 .description(name)
+                 .hardware(hardwareRequest)
+                 .rsaKey(options.getPublicKey())
+                 .password(privateKey == null ? password : null)
+                 .applianceId(image.getId())
+                 .dataCenterId(dataCenterId)
+                 .powerOn(Boolean.TRUE).build();
+
+         logger.trace("<< provisioning server '%s'", serverRequest);
+
+         server = api.serverApi().create(serverRequest);
+
+         waitServerUntilAvailable.apply(server);
+
+         updateServer = api.serverApi().get(server.id());
+
+         Map<Integer, Integer> portsRange = 
getPortRangesFromList(inboundPorts);
+         List<FirewallPolicy.Rule.CreatePayload> rules = new 
ArrayList<FirewallPolicy.Rule.CreatePayload>();
+
+         for (Map.Entry<Integer, Integer> range : portsRange.entrySet()) {
+            FirewallPolicy.Rule.CreatePayload rule = 
FirewallPolicy.Rule.CreatePayload.builder()
+                    .portFrom(range.getKey())
+                    .portTo(range.getValue())
+                    .protocol(Types.RuleProtocol.TCP)
+                    .build();
+            rules.add(rule);
+         }
+         if (inboundPorts.length > 0) {
+            FirewallPolicy rule = 
api.firewallPolicyApi().create(FirewallPolicy.CreateFirewallPolicy.create(server.name()
 + " firewall policy", "desc", rules));
+            api.serverApi().addFirewallPolicy(updateServer.id(), 
updateServer.ips().get(0).id(), rule.id());
+            waitServerUntilAvailable.apply(server);
+         }
+
+         logger.trace(">> provisioning complete for server. returned id='%s'", 
server.id());
+
+      } catch (Exception ex) {
+         logger.error(ex, ">> failed to provision server. rollbacking..");
+         if (server != null) {
+            destroyNode(server.id());
+         }
+         throw Throwables.propagate(ex);
+      }
+
+      LoginCredentials serverCredentials = LoginCredentials.builder()
+              .user(loginUser)
+              .password(password)
+              .privateKey(privateKey)
+              .build();
+
+      return new NodeAndInitialCredentials<Server>(updateServer, 
updateServer.id(), serverCredentials);
+   }
+
+   @Override
+   public List<HardwareFlavour> listHardwareProfiles() {
+      return api.serverApi().listHardwareFlavours();
+   }
+
+   @Override
+   public Iterable<SingleServerAppliance> listImages() {
+      GenericQueryOptions options = new GenericQueryOptions();
+      options.options(0, 0, null, null, null);
+      List<ServerAppliance> list = api.serverApplianceApi().list(options);
+      List<SingleServerAppliance> results = new 
ArrayList<SingleServerAppliance>();
+      for (ServerAppliance appliance : list) {
+         List<SingleServerAppliance.AvailableDataCenters> availableDatacenters 
= new ArrayList<SingleServerAppliance.AvailableDataCenters>();
+         for (String dcId : appliance.availableDataCenters()) {
+            
availableDatacenters.add(SingleServerAppliance.AvailableDataCenters.create(dcId,
 ""));
+         }
+         results.add(SingleServerAppliance.builder()
+                 .id(appliance.id())
+                 .name(appliance.name())
+                 .availableDataCenters(availableDatacenters)
+                 .osInstallationBase(appliance.osInstallationBase())
+                 .osFamily(appliance.osFamily())
+                 .os(appliance.os())
+                 .osVersion(appliance.osVersion())
+                 .osArchitecture(appliance.osArchitecture())
+                 .osImageType(appliance.osImageType())
+                 .minHddSize(appliance.minHddSize())
+                 .type(appliance.type())
+                 .state(appliance.state())
+                 .version(appliance.version())
+                 .categories(appliance.categories())
+                 .eulaUrl(appliance.eulaUrl())
+                 .build());
+      }
+      return results;
+   }
+
+   @Override
+   public SingleServerAppliance getImage(String id) {
+      // try search images
+      logger.trace("<< searching for image with id=%s", id);
+      GenericQueryOptions options = new GenericQueryOptions();
+      options.options(0, 0, null, id, null);
+      try {
+         List<ServerAppliance> list = api.serverApplianceApi().list(options);
+         if (list.size() > 0) {
+            ServerAppliance appliance = list.get(0);
+            List<SingleServerAppliance.AvailableDataCenters> 
availableDatacenters = new 
ArrayList<SingleServerAppliance.AvailableDataCenters>();
+            for (String dcId : appliance.availableDataCenters()) {
+               
availableDatacenters.add(SingleServerAppliance.AvailableDataCenters.create(dcId,
 ""));
+            }
+            SingleServerAppliance image = 
SingleServerAppliance.create(appliance.id(), appliance.name(), 
availableDatacenters, appliance.osInstallationBase(),
+                    appliance.osFamily(), appliance.os(), 
appliance.osVersion(), appliance.osArchitecture(), appliance.osImageType(), 
appliance.minHddSize(),
+                    appliance.type(), appliance.state(), appliance.version(), 
appliance.categories(), appliance.eulaUrl());
+            logger.trace(">> found image [%s].", image.name());
+            return image;
+         }
+      } catch (Exception ex) {
+         throw new ResourceNotFoundException("No image with id '" + id + "' 
was found");
+      }
+      throw new ResourceNotFoundException("No image with id '" + id + "' was 
found");
+   }
+
+   @Override
+   public Iterable<DataCenter> listLocations() {
+      return api.dataCenterApi().list();
+   }
+
+   @Override
+   public Server getNode(String id) {
+      return api.serverApi().get(id);
+   }
+
+   @Override
+   public void destroyNode(String id) {
+      checkState(cleanupResources.cleanupNode(id), "server(%s) and its 
resources still there after deleting!?", id);
+   }
+
+   @Override
+   public void rebootNode(String id) {
+      waitServerUntilAvailable.apply(getNode(id));
+      api.serverApi().updateStatus(id, 
Server.UpdateStatus.create(Types.ServerAction.REBOOT, 
Types.ServerActionMethod.HARDWARE));
+   }
+
+   @Override
+   public void resumeNode(String id) {
+      api.serverApi().updateStatus(id, 
Server.UpdateStatus.create(Types.ServerAction.POWER_ON, 
Types.ServerActionMethod.HARDWARE));
+   }
+
+   @Override
+   public void suspendNode(String id) {
+      waitServerUntilAvailable.apply(getNode(id));
+      api.serverApi().updateStatus(id, 
Server.UpdateStatus.create(Types.ServerAction.POWER_OFF, 
Types.ServerActionMethod.HARDWARE));
+   }
+
+   @Override
+   public Iterable<Server> listNodes() {
+      return api.serverApi().list();
+   }
+
+   @Override
+   public Iterable<Server> listNodesByIds(final Iterable<String> ids) {
+      return filter(listNodes(), new Predicate<Server>() {
+         @Override
+         public boolean apply(Server server) {
+            return contains(ids, server);
+         }
+      });
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/config/OneAndOneComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/config/OneAndOneComputeServiceContextModule.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/config/OneAndOneComputeServiceContextModule.java
new file mode 100644
index 0000000..ba8fb25
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/config/OneAndOneComputeServiceContextModule.java
@@ -0,0 +1,116 @@
+/*
+ * 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.oneandone.rest.compute.config;
+
+import com.google.common.base.Function;
+import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Predicate;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+import java.util.concurrent.TimeUnit;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import org.apache.jclouds.oneandone.rest.OneAndOneApi;
+import 
org.apache.jclouds.oneandone.rest.compute.OneandoneComputeServiceAdapter;
+import org.apache.jclouds.oneandone.rest.compute.function.DataCenterToLocation;
+import 
org.apache.jclouds.oneandone.rest.compute.function.HardwareFlavourToHardware;
+import org.apache.jclouds.oneandone.rest.compute.function.HddToVolume;
+import org.apache.jclouds.oneandone.rest.compute.function.ServerToNodeMetadata;
+import 
org.apache.jclouds.oneandone.rest.compute.function.SingleServerApplianceToImage;
+import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_PREDICATE_SERVER;
+import org.apache.jclouds.oneandone.rest.domain.DataCenter;
+import org.apache.jclouds.oneandone.rest.domain.HardwareFlavour;
+import org.apache.jclouds.oneandone.rest.domain.Hdd;
+import org.apache.jclouds.oneandone.rest.domain.Server;
+import org.apache.jclouds.oneandone.rest.domain.SingleServerAppliance;
+import org.apache.jclouds.oneandone.rest.domain.Types;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.domain.internal.ArbitraryCpuRamTemplateBuilderImpl;
+import org.jclouds.compute.domain.internal.TemplateBuilderImpl;
+import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
+import 
org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey;
+import org.jclouds.compute.reference.ComputeServiceConstants.PollPeriod;
+import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
+import org.jclouds.domain.Location;
+import static org.jclouds.util.Predicates2.retry;
+
+public class OneAndOneComputeServiceContextModule extends
+        ComputeServiceAdapterContextModule<Server, HardwareFlavour, 
SingleServerAppliance, DataCenter> {
+
+   @SuppressWarnings("unchecked")
+   @Override
+   protected void configure() {
+      super.configure();
+
+      install(new LocationsFromComputeServiceAdapterModule<Server, 
HardwareFlavour, SingleServerAppliance, DataCenter>() {
+      });
+
+      bind(new TypeLiteral<ComputeServiceAdapter<Server, HardwareFlavour, 
SingleServerAppliance, DataCenter>>() {
+      }).to(OneandoneComputeServiceAdapter.class);
+
+      
bind(TemplateBuilderImpl.class).to(ArbitraryCpuRamTemplateBuilderImpl.class);
+
+      
bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
+
+      bind(new TypeLiteral<Function<Server, NodeMetadata>>() {
+      }).to(ServerToNodeMetadata.class);
+
+      bind(new TypeLiteral<Function<SingleServerAppliance, Image>>() {
+      }).to(SingleServerApplianceToImage.class);
+
+      bind(new TypeLiteral<Function<Hdd, Volume>>() {
+      }).to(HddToVolume.class);
+
+      bind(new TypeLiteral<Function<HardwareFlavour, Hardware>>() {
+      }).to(HardwareFlavourToHardware.class);
+
+      bind(new TypeLiteral<Function<DataCenter, Location>>() {
+      }).to(DataCenterToLocation.class);
+
+   }
+
+   @Provides
+   @Singleton
+   @Named(POLL_PREDICATE_SERVER)
+   Predicate<Server> provideServerAvailablePredicate(final OneAndOneApi api, 
Timeouts timeouts, PollPeriod pollPeriod) {
+      return retry(new ServerAvailablePredicate(api),
+              timeouts.nodeRunning, pollPeriod.pollInitialPeriod, 
pollPeriod.pollMaxPeriod, TimeUnit.SECONDS);
+   }
+
+   static class ServerAvailablePredicate implements Predicate<Server> {
+
+      private final OneAndOneApi api;
+
+      public ServerAvailablePredicate(OneAndOneApi api) {
+         this.api = checkNotNull(api, "api must not be null");
+      }
+
+      @Override
+      public boolean apply(Server server) {
+         checkNotNull(server, "Server");
+         server = api.serverApi().get(server.id());
+         return !((server.status().state() != Types.ServerState.POWERED_OFF
+                 && server.status().state() != Types.ServerState.POWERED_ON)
+                 || server.status().percent() != 0);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/config/OneAndOneRateLimitModule.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/config/OneAndOneRateLimitModule.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/config/OneAndOneRateLimitModule.java
new file mode 100644
index 0000000..dd79ea7
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/config/OneAndOneRateLimitModule.java
@@ -0,0 +1,30 @@
+/*
+ * 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.oneandone.rest.compute.config;
+
+import com.google.inject.AbstractModule;
+import 
org.apache.jclouds.oneandone.rest.handlers.OneAndOneRateLimitRetryHandler;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.annotation.ClientError;
+
+public class OneAndOneRateLimitModule extends AbstractModule {
+   @Override
+   protected void configure() {
+      
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(OneAndOneRateLimitRetryHandler.class);
+   }
+}
+

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/DataCenterToLocation.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/DataCenterToLocation.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/DataCenterToLocation.java
new file mode 100644
index 0000000..982a171
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/DataCenterToLocation.java
@@ -0,0 +1,48 @@
+/*
+ * 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.oneandone.rest.compute.function;
+
+import com.google.common.base.Function;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import javax.inject.Singleton;
+import org.apache.jclouds.oneandone.rest.domain.DataCenter;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.location.suppliers.all.JustProvider;
+
+@Singleton
+public class DataCenterToLocation implements Function<DataCenter, 
org.jclouds.domain.Location> {
+
+   private final JustProvider justProvider;
+
+   // allow us to lazy discover the provider of a resource
+   @javax.inject.Inject
+   DataCenterToLocation(JustProvider justProvider) {
+      this.justProvider = justProvider;
+   }
+
+   @Override
+   public org.jclouds.domain.Location apply(final DataCenter center) {
+
+      final LocationBuilder builder = new LocationBuilder();
+      builder.id(center.id());
+      builder.description(center.location());
+      builder.parent(getOnlyElement(justProvider.get()));
+      builder.scope(LocationScope.REGION);
+      return builder.build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/HardwareFlavourToHardware.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/HardwareFlavourToHardware.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/HardwareFlavourToHardware.java
new file mode 100644
index 0000000..ab1a850
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/HardwareFlavourToHardware.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.apache.jclouds.oneandone.rest.compute.function;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.jclouds.oneandone.rest.domain.HardwareFlavour;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.domain.VolumeBuilder;
+
+public class HardwareFlavourToHardware implements Function<HardwareFlavour, 
Hardware> {
+
+   @Override
+   public Hardware apply(HardwareFlavour from) {
+      double minRamSize = (int) from.hardware().ram();
+      if (from.hardware().ram() < 1) {
+         minRamSize = 0.5;
+      }
+      List<Volume> volumes = new ArrayList<Volume>();
+      for (HardwareFlavour.Hardware.Hdd hdd : from.hardware().hdds()) {
+         Volume vol = new VolumeBuilder()
+                 .bootDevice(hdd.isMain())
+                 .device("hdd")
+                 .type(Volume.Type.LOCAL)
+                 .size((float) hdd.size())
+                 .build();
+         volumes.add(vol);
+      }
+
+      List<Processor> processors = new ArrayList<Processor>();
+      for (int i = 0; i < from.hardware().coresPerProcessor(); i++) {
+         Processor proc = new Processor(from.hardware().vcore(), 1d);
+         processors.add(proc);
+      }
+      final HardwareBuilder builder;
+      builder = new HardwareBuilder()
+              .ids(from.id())
+              .name(from.name())
+              .ram((int) (minRamSize * 1024))
+              .volumes(volumes)
+              .processors(ImmutableList.copyOf(processors));
+      return builder.build();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/HddToVolume.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/HddToVolume.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/HddToVolume.java
new file mode 100644
index 0000000..62ed4cc
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/HddToVolume.java
@@ -0,0 +1,40 @@
+/*
+ * 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.oneandone.rest.compute.function;
+
+import com.google.common.base.Function;
+import static com.google.common.base.Preconditions.checkNotNull;
+import org.apache.jclouds.oneandone.rest.domain.Hdd;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.domain.VolumeBuilder;
+
+public class HddToVolume implements Function<Hdd, Volume> {
+   
+   @Override
+   public Volume apply(Hdd volume) {
+      checkNotNull(volume, "Null storage");
+      
+      return new VolumeBuilder()
+              .id(volume.id())
+              .size((float) volume.size())
+              .durable(true)
+              .bootDevice(volume.isMain())
+              .type(Volume.Type.LOCAL)
+              .build();
+      
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/ServerToNodeMetadata.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/ServerToNodeMetadata.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/ServerToNodeMetadata.java
new file mode 100644
index 0000000..5ff4284
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/ServerToNodeMetadata.java
@@ -0,0 +1,188 @@
+/*
+ * 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.oneandone.rest.compute.function;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.not;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import static com.google.common.collect.Iterables.find;
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.jclouds.oneandone.rest.OneAndOneApi;
+import org.apache.jclouds.oneandone.rest.domain.DataCenter;
+import org.apache.jclouds.oneandone.rest.domain.Hdd;
+import org.apache.jclouds.oneandone.rest.domain.Server;
+import org.apache.jclouds.oneandone.rest.domain.ServerIp;
+import org.apache.jclouds.oneandone.rest.domain.Types.ServerState;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.util.AutomaticHardwareIdSpec;
+import org.jclouds.domain.Location;
+import static org.jclouds.location.predicates.LocationPredicates.idEquals;
+import org.jclouds.util.InetAddresses2;
+
+public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
+
+   private final Supplier<Set<? extends Location>> locations;
+   private final Supplier<Map<String, ? extends Hardware>> hardwareFlavors;
+   private final Supplier<Map<String, ? extends Image>> images;
+   private final Function<Hdd, Volume> fnVolume;
+   private final OneAndOneApi api;
+
+   private final GroupNamingConvention groupNamingConvention;
+
+   @Inject
+   public ServerToNodeMetadata(Function<Hdd, Volume> fnVolume,
+           @Memoized Supplier<Set<? extends Location>> locations,
+           Supplier<Map<String, ? extends Hardware>> hardwareFlavors,
+           Supplier<Map<String, ? extends Image>> images,
+           OneAndOneApi api,
+           GroupNamingConvention.Factory groupNamingConvention) {
+      this.hardwareFlavors = hardwareFlavors;
+      this.images = images;
+      this.locations = locations;
+      this.api = api;
+      this.fnVolume = fnVolume;
+      this.groupNamingConvention = groupNamingConvention.createWithoutPrefix();
+   }
+
+   @Override
+   public NodeMetadata apply(final Server server) {
+      checkNotNull(server, "Null server");
+
+      DataCenter dataCenter = 
api.dataCenterApi().get(server.datacenter().id());
+      Location location = find(locations.get(), idEquals(dataCenter.id()));
+      Hardware hardware = null;
+      //check if the server was built on a hardware flavour(Fixed instance)
+      if (server.hardware().fixedInstanceSizeId() != null && 
!"0".equals(server.hardware().fixedInstanceSizeId())) {
+         hardware = 
hardwareFlavors.get().get(server.hardware().fixedInstanceSizeId());
+
+      } else {
+         List<Volume> volumes = Lists.newArrayList();
+         //customer hardware
+         double size = 0d;
+         double minRam = server.hardware().ram();
+         List<Hdd> hdds = server.hardware().hdds();
+
+         if (server.hardware().hdds().isEmpty()) {
+            hdds = api.serverApi().getHardware(server.id()).hdds();
+         }
+
+         size = getHddSize(hdds);
+         volumes = convertHddToVolume(hdds);
+
+         if (minRam < 1) {
+            minRam = 512;
+         } else {
+            minRam = minRam * 1024;
+         }
+
+         List<Processor> processors = new ArrayList<Processor>();
+         for (int i = 0; i < server.hardware().vcore(); i++) {
+            Processor proc = new 
Processor(server.hardware().coresPerProcessor(), 1d);
+            processors.add(proc);
+         }
+         AutomaticHardwareIdSpec id = 
AutomaticHardwareIdSpec.automaticHardwareIdSpecBuilder(server.hardware().vcore(),
 (int) minRam, Optional.of((float) size));
+         hardware = new HardwareBuilder()
+                 .ids(id.toString())
+                 .ram((int) minRam)
+                 .processors(ImmutableList.copyOf(processors))
+                 .hypervisor("kvm")
+                 .volumes(volumes)
+                 .location(location)
+                 .build();
+
+      }
+
+      // Collect ips
+      List<String> addresses = Lists.transform(server.ips(), new 
Function<ServerIp, String>() {
+         @Override
+         public String apply(ServerIp in) {
+            return in.ip();
+         }
+      });
+
+      Image image = images.get().get(server.image().id());
+      // Build node
+      NodeMetadataBuilder nodeBuilder = new NodeMetadataBuilder();
+      nodeBuilder.ids(server.id())
+              .group(groupNamingConvention.extractGroup(server.name()))
+              .name(server.name())
+              .backendStatus(server.status().state().toString())
+              .status(mapStatus(server.status().state()))
+              .hardware(hardware)
+              .operatingSystem(image.getOperatingSystem())
+              .location(location)
+              .privateAddresses(Iterables.filter(addresses, 
InetAddresses2.IsPrivateIPAddress.INSTANCE))
+              .publicAddresses(Iterables.filter(addresses, 
not(InetAddresses2.IsPrivateIPAddress.INSTANCE)));
+
+      return nodeBuilder.build();
+   }
+
+   private double getHddSize(List<Hdd> hdds) {
+      double size = 0d;
+      for (Hdd storage : hdds) {
+         size += storage.size();
+      }
+      return size;
+   }
+
+   private List<Volume> convertHddToVolume(List<Hdd> hdds) {
+      List<Volume> volumes = Lists.newArrayList();
+      for (Hdd storage : hdds) {
+         volumes.add(fnVolume.apply(storage));
+      }
+      return volumes;
+   }
+
+   static NodeMetadata.Status mapStatus(ServerState status) {
+      if (status == null) {
+         return NodeMetadata.Status.UNRECOGNIZED;
+      }
+      switch (status) {
+         case CONFIGURING:
+         case DEPLOYING:
+         case POWERING_OFF:
+         case POWERING_ON:
+         case REBOOTING:
+         case REMOVING:
+            return NodeMetadata.Status.PENDING;
+         case POWERED_OFF:
+            return NodeMetadata.Status.SUSPENDED;
+         case POWERED_ON:
+            return NodeMetadata.Status.RUNNING;
+         default:
+            return NodeMetadata.Status.UNRECOGNIZED;
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/SingleServerApplianceToImage.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/SingleServerApplianceToImage.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/SingleServerApplianceToImage.java
new file mode 100644
index 0000000..71ab088
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/function/SingleServerApplianceToImage.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.apache.jclouds.oneandone.rest.compute.function;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import static com.google.common.collect.Iterables.tryFind;
+import static java.util.Arrays.asList;
+import java.util.Map;
+import org.apache.jclouds.oneandone.rest.domain.SingleServerAppliance;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+
+public class SingleServerApplianceToImage implements 
Function<SingleServerAppliance, Image> {
+
+   private static final Map<String, OsFamily> OTHER_OS_MAP = 
ImmutableMap.<String, OsFamily>builder()
+           .put("Others", OsFamily.FREEBSD)
+           .put("Other", OsFamily.FREEBSD)
+           .build();
+
+   @Override
+   public Image apply(SingleServerAppliance from) {
+      OsFamily osFamily = 
findInStandardFamilies(from.osVersion()).or(findInOtherOSMap(from.osVersion())).or(OsFamily.UNRECOGNIZED);
+      OperatingSystem os = OperatingSystem.builder()
+              .description(osFamily.value())
+              .family(osFamily)
+              .version(parseVersion(from.os()))
+              .is64Bit(is64Bit(from.osArchitecture()))
+              .build();
+
+      return new ImageBuilder()
+              .ids(from.id())
+              .name(from.name())
+              .status(Image.Status.AVAILABLE)
+              .operatingSystem(os)
+              .build();
+   }
+
+   static String parseVersion(String from) {
+      if (from != null) {
+         String[] split = from.toLowerCase().split("^\\D*(?=\\d)");
+
+         if (split.length >= 2) {
+            return split[1];
+         }
+      }
+      return "non";
+   }
+
+   static boolean is64Bit(int architecture) {
+      return architecture != 32;
+
+   }
+
+   private static Optional<OsFamily> findInStandardFamilies(final String 
osFamily) {
+      return tryFind(asList(OsFamily.values()), new Predicate<OsFamily>() {
+         @Override
+         public boolean apply(OsFamily input) {
+            return 
osFamily.toLowerCase().contains(input.value().toLowerCase());
+         }
+      });
+   }
+
+   private static Optional<OsFamily> findInOtherOSMap(final String label) {
+      return tryFind(OTHER_OS_MAP.keySet(), new Predicate<String>() {
+         @Override
+         public boolean apply(String input) {
+            return label.contains(input);
+         }
+      }).transform(new Function<String, OsFamily>() {
+         @Override
+         public OsFamily apply(String input) {
+            return OTHER_OS_MAP.get(input);
+         }
+      });
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/strategy/CleanupResources.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/strategy/CleanupResources.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/strategy/CleanupResources.java
new file mode 100644
index 0000000..f097602
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/compute/strategy/CleanupResources.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jclouds.oneandone.rest.compute.strategy;
+
+import java.util.List;
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import org.apache.jclouds.oneandone.rest.OneAndOneApi;
+import org.apache.jclouds.oneandone.rest.domain.FirewallPolicy;
+import org.apache.jclouds.oneandone.rest.domain.Server;
+import org.apache.jclouds.oneandone.rest.domain.options.GenericQueryOptions;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+
+@Singleton
+public class CleanupResources {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final OneAndOneApi api;
+
+   @Inject
+   CleanupResources(OneAndOneApi oneandoneapi) {
+      this.api = oneandoneapi;
+   }
+
+   public boolean cleanupNode(final String id) {
+      Server server = api.serverApi().get(id);
+      if (server == null) {
+         return true;
+      }
+
+      logger.debug(">> destroying %s ...", server.id());
+      deleteServer(server);
+      deleteFirewallPolicy(server);
+
+      return true;
+   }
+
+   private void deleteFirewallPolicy(Server server) {
+      try {
+         GenericQueryOptions options = new GenericQueryOptions().options(0, 0, 
null, server.name() + " firewall policy", null);
+         List<FirewallPolicy> firewallRules = 
api.firewallPolicyApi().list(options);
+         for (FirewallPolicy firewallRule : firewallRules) {
+            api.firewallPolicyApi().delete(firewallRule.id());
+         }
+      } catch (Exception ex) {
+         logger.debug("no firewall policies found for %s ...", server.id());
+      }
+   }
+
+   private void deleteServer(Server server) {
+      api.serverApi().delete(server.id());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneConstants.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneConstants.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneConstants.java
deleted file mode 100644
index 9dde8b8..0000000
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneConstants.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.jclouds.oneandone.rest.config;
-
-import com.google.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_MAX_PERIOD;
-import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_PERIOD;
-import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_TIMEOUT;
-
-@Singleton
-public class OneAndOneConstants {
-
-   @Inject
-   @Named(POLL_TIMEOUT)
-   private String pollTimeout;
-
-   @Inject
-   @Named(POLL_PERIOD)
-   private String pollPeriod;
-
-   @Inject
-   @Named(POLL_MAX_PERIOD)
-   private String pollMaxPeriod;
-
-   public long pollTimeout() {
-      return Long.parseLong(pollTimeout);
-   }
-
-   public long pollPeriod() {
-      return Long.parseLong(pollPeriod);
-   }
-
-   public long pollMaxPeriod() {
-      return Long.parseLong(pollMaxPeriod);
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneHttpApiModule.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneHttpApiModule.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneHttpApiModule.java
index ce20590..86b87f6 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneHttpApiModule.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneHttpApiModule.java
@@ -23,12 +23,11 @@ import java.util.concurrent.TimeUnit;
 import javax.inject.Named;
 import org.apache.jclouds.oneandone.rest.OneAndOneApi;
 import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_PREDICATE_PRIVATE_NETWORK;
-import static 
org.apache.jclouds.oneandone.rest.config.OneAndOneProperties.POLL_PREDICATE_SERVER;
 import org.apache.jclouds.oneandone.rest.domain.PrivateNetwork;
-import org.apache.jclouds.oneandone.rest.domain.Server;
 import org.apache.jclouds.oneandone.rest.domain.Types;
 import org.apache.jclouds.oneandone.rest.handlers.OneAndOneHttpErrorHandler;
 import org.apache.jclouds.oneandone.rest.ids.ServerPrivateNetworkRef;
+import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.http.HttpErrorHandler;
 import org.jclouds.http.annotation.ClientError;
 import org.jclouds.http.annotation.Redirection;
@@ -57,40 +56,10 @@ public class OneAndOneHttpApiModule extends 
HttpApiModule<OneAndOneApi> {
 
    @Provides
    @Named(POLL_PREDICATE_PRIVATE_NETWORK)
-   Predicate<ServerPrivateNetworkRef> 
providePrivateNetworkReadyPredicate(final OneAndOneApi api, OneAndOneConstants 
constants) {
+   Predicate<ServerPrivateNetworkRef> 
providePrivateNetworkReadyPredicate(final OneAndOneApi api, 
ComputeServiceConstants.Timeouts timeouts, ComputeServiceConstants.PollPeriod 
pollPeriod) {
       return retry(new PrivateNetworkReadyPredicate(
               api),
-              constants.pollTimeout(), constants.pollPeriod(), 
constants.pollMaxPeriod(), TimeUnit.SECONDS);
-   }
-
-   @Provides
-   @Named(POLL_PREDICATE_SERVER)
-   Predicate<Server> provideServerReadyPredicate(final OneAndOneApi api, 
OneAndOneConstants constants) {
-      return retry(new ServerReadyPredicate(
-              api),
-              constants.pollTimeout(), constants.pollPeriod(), 
constants.pollMaxPeriod(), TimeUnit.SECONDS);
-   }
-
-   static class ServerReadyPredicate implements Predicate<Server> {
-
-      private final OneAndOneApi api;
-
-      public ServerReadyPredicate(OneAndOneApi api) {
-         this.api = checkNotNull(api, "api must not be null");
-      }
-
-      @Override
-      public boolean apply(Server server) {
-         checkNotNull(server, "Server");
-         server = api.serverApi().get(server.id());
-         if ((server.status().state() != Types.ServerState.POWERED_OFF
-                 && server.status().state() != Types.ServerState.POWERED_ON)
-                 || server.status().percent() != 0) {
-            return false;
-         } else {
-            return true;
-         }
-      }
+              timeouts.nodeRunning, pollPeriod.pollInitialPeriod, 
pollPeriod.pollMaxPeriod, TimeUnit.SECONDS);
    }
 
    static class PrivateNetworkReadyPredicate implements 
Predicate<ServerPrivateNetworkRef> {

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneProperties.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneProperties.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneProperties.java
index 469a230..ffe39aa 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneProperties.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/config/OneAndOneProperties.java
@@ -19,9 +19,8 @@ package org.apache.jclouds.oneandone.rest.config;
 public final class OneAndOneProperties {
 
    public static final String POLL_PREDICATE_SERVER = 
"jclouds.oneandone.rest.predicate.server";
+   public static final String POLL_PREDICATE_SERVER_RUNNING = 
"jclouds.oneandone.rest.predicate.serveron";
    public static final String POLL_PREDICATE_PRIVATE_NETWORK = 
"jclouds.oneandone.rest.predicate.privatenetwork";
-   public static final String AUTH_TOKEN = "oneandone.identity";
+   public static final String POLL_PREDICATE_SNAPSHOT = 
"jclouds.oneandone.rest.predicate.snapshot";
    public static final String POLL_TIMEOUT = 
"jclouds.oneandone.rest.poll.timeout";
-   public static final String POLL_PERIOD = 
"jclouds.oneandone.rest.operation.poll.initial-period";
-   public static final String POLL_MAX_PERIOD = 
"jclouds.oneandone.rest.operation.poll.max-period";
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/DataCenter.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/DataCenter.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/DataCenter.java
index 95e2bf3..0fc4aad 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/DataCenter.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/DataCenter.java
@@ -17,18 +17,22 @@
 package org.apache.jclouds.oneandone.rest.domain;
 
 import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
 @AutoValue
 public abstract class DataCenter {
-    public abstract String id();
 
-    public abstract String countryCode();
+   public abstract String id();
 
-    public abstract String location();
+   @Nullable
+   public abstract String countryCode();
 
-    @SerializedNames({"id", "country_code", "location"})
-    public static DataCenter create(String id, String countryCode, String 
location) {
-        return new AutoValue_DataCenter(id, countryCode, location);
-    }
+   @Nullable
+   public abstract String location();
+
+   @SerializedNames({"id", "country_code", "location"})
+   public static DataCenter create(String id, String countryCode, String 
location) {
+      return new AutoValue_DataCenter(id, countryCode, location);
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Hardware.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Hardware.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Hardware.java
index 30480f5..2637a18 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Hardware.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Hardware.java
@@ -19,11 +19,15 @@ package org.apache.jclouds.oneandone.rest.domain;
 import com.google.auto.value.AutoValue;
 import java.util.List;
 import org.apache.jclouds.oneandone.rest.domain.Hdd.CreateHdd;
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.json.SerializedNames;
 
 @AutoValue
 public abstract class Hardware {
 
+   @Nullable
+   public abstract String fixedInstanceSizeId();
+
    public abstract double vcore();
 
    public abstract double coresPerProcessor();
@@ -32,9 +36,9 @@ public abstract class Hardware {
 
    public abstract List<Hdd> hdds();
 
-   @SerializedNames({"vcore", "cores_per_processor", "ram", "hdds"})
-   public static Hardware create(double vcore, double coresPerProcessor, 
double ram, List<Hdd> hdds) {
-      return new AutoValue_Hardware(vcore, coresPerProcessor, ram, hdds);
+   @SerializedNames({"fixed_instance_size_id", "vcore", "cores_per_processor", 
"ram", "hdds"})
+   public static Hardware create(String fixedInstanceSizeId, double vcore, 
double coresPerProcessor, double ram, List<Hdd> hdds) {
+      return new AutoValue_Hardware(fixedInstanceSizeId, vcore, 
coresPerProcessor, ram, hdds);
    }
 
    @AutoValue

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Image.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Image.java 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Image.java
index 19acb9f..c937503 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Image.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Image.java
@@ -34,6 +34,9 @@ public abstract class Image {
    public abstract String name();
 
    @Nullable
+   public abstract DataCenter datacenter();
+
+   @Nullable
    public abstract OSFamliyType osFamily();
 
    @Nullable
@@ -77,9 +80,9 @@ public abstract class Image {
 
    public abstract String creationDate();
 
-   @SerializedNames({"id", "name", "os_family", "os", "os_version", 
"availableSites", "architecture", "os_image_type", "type", "min_hdd_size", 
"licenses", "state", "description", "hdds", "server_id", "frequency", 
"numImages", "creation_date"})
-   public static Image create(String id, String name, OSFamliyType osFamily, 
OSType os, String osVersion, List<String> availableSites, int architecture, 
String osImageType, ImageType type, int minHddSize, List<Licenses> licenses, 
String state, String description, List<Hdd> hdds, String serverId, 
ImageFrequency frequency, int numImages, String creationDate) {
-      return new AutoValue_Image(id, name, osFamily, os, osVersion, 
availableSites == null ? ImmutableList.<String>of() : availableSites,
+   @SerializedNames({"id", "name", "datacenter", "os_family", "os", 
"os_version", "availableSites", "architecture", "os_image_type", "type", 
"min_hdd_size", "licenses", "state", "description", "hdds", "server_id", 
"frequency", "numImages", "creation_date"})
+   public static Image create(String id, String name, DataCenter datacenter, 
OSFamliyType osFamily, OSType os, String osVersion, List<String> 
availableSites, int architecture, String osImageType, ImageType type, int 
minHddSize, List<Licenses> licenses, String state, String description, 
List<Hdd> hdds, String serverId, ImageFrequency frequency, int numImages, 
String creationDate) {
+      return new AutoValue_Image(id, name, datacenter, osFamily, os, 
osVersion, availableSites == null ? ImmutableList.<String>of() : availableSites,
               architecture, osImageType, type, minHddSize, licenses == null ? 
ImmutableList.<Licenses>of() : licenses, state,
               description, hdds == null ? ImmutableList.<Hdd>of() : hdds, 
serverId, frequency, numImages, creationDate);
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Server.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Server.java 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Server.java
index b044776..c2d754c 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Server.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Server.java
@@ -205,10 +205,13 @@ public abstract class Server {
       @Nullable
       public abstract String monitoringPolicyId();
 
-      @SerializedNames({"name", "description", "hardware", "appliance_id", 
"datacenter_id", "password", "region_id", "power_on", "firewall_policy_id", 
"ip_id", "loadr_balancer_id", "monitoring_policy_id"})
+      @Nullable
+      public abstract String rsaKey();
+
+      @SerializedNames({"name", "description", "hardware", "appliance_id", 
"datacenter_id", "password", "region_id", "power_on", "firewall_policy_id", 
"ip_id", "loadr_balancer_id", "monitoring_policy_id", "rsa_key"})
       public static CreateServer create(final String name, final String 
description, final Hardware.CreateHardware hardware, final String applianceId,
               final String dataCenterId, final String password, final String 
regionId, final Boolean powerOn, final String firewallPolicyId,
-              final String ipId, final String loadrBalancerId, final String 
monitoringPolicyId) {
+              final String ipId, final String loadrBalancerId, final String 
monitoringPolicyId, final String rsaKey) {
          return builder()
                  .name(name)
                  .description(description)
@@ -220,6 +223,7 @@ public abstract class Server {
                  .powerOn(powerOn)
                  .firewallPolicyId(firewallPolicyId)
                  .ipId(ipId)
+                 .rsaKey(rsaKey)
                  .loadrBalancerId(loadrBalancerId)
                  .monitoringPolicyId(monitoringPolicyId)
                  .build();
@@ -256,6 +260,8 @@ public abstract class Server {
 
          public abstract Builder monitoringPolicyId(String monitoringPolicyId);
 
+         public abstract Builder rsaKey(String rsaKey);
+
          public abstract CreateServer build();
       }
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/ServerAppliance.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/ServerAppliance.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/ServerAppliance.java
new file mode 100644
index 0000000..aa11d50
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/ServerAppliance.java
@@ -0,0 +1,77 @@
+/*
+ * 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.oneandone.rest.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.apache.jclouds.oneandone.rest.domain.Types.ApplianceType;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class ServerAppliance {
+
+   public abstract String id();
+
+   public abstract String name();
+
+   @Nullable
+   public abstract List<String> availableDataCenters();
+
+   @Nullable
+   public abstract String osInstallationBase();
+
+   @Nullable
+   public abstract Types.OSFamliyType osFamily();
+
+   @Nullable
+   public abstract String os();
+
+   @Nullable
+   public abstract String osVersion();
+
+   public abstract int osArchitecture();
+
+   @Nullable
+   public abstract Types.OSImageType osImageType();
+
+   public abstract int minHddSize();
+
+   @Nullable
+   public abstract ApplianceType type();
+
+   @Nullable
+   public abstract String state();
+
+   @Nullable
+   public abstract String version();
+
+   @Nullable
+   public abstract List<String> categories();
+
+   @Nullable
+   public abstract String eulaUrl();
+
+   @SerializedNames({"id", "name", "available_datacenters", 
"os_installation_base", "os_family", "os", "os_version", "os_architecture", 
"os_image_type",
+      "min_hdd_size", "type", "state", "version", "categories", "eula_url"})
+   public static ServerAppliance create(String id, String name, List<String> 
availableDataCenters, String osInstallationBase, Types.OSFamliyType osFamily, 
String os,
+           String osVersion, int osArchitecture, Types.OSImageType 
osImageType, int minHddSize, ApplianceType type, String state, String version, 
List<String> categories, String eulaUrl) {
+      return new AutoValue_ServerAppliance(id, name, availableDataCenters == 
null ? ImmutableList.<String>of() : ImmutableList.copyOf(availableDataCenters), 
osInstallationBase, osFamily, os, osVersion, osArchitecture, osImageType, 
minHddSize, type, state, version, categories == null ? 
ImmutableList.<String>of() : ImmutableList.copyOf(categories), eulaUrl);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/SingleServerAppliance.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/SingleServerAppliance.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/SingleServerAppliance.java
new file mode 100644
index 0000000..8ba0772
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/SingleServerAppliance.java
@@ -0,0 +1,154 @@
+/*
+ * 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.oneandone.rest.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class SingleServerAppliance {
+
+   public abstract String id();
+
+   public abstract String name();
+
+   @Nullable
+   public abstract List<AvailableDataCenters> availableDataCenters();
+
+   @Nullable
+   public abstract String osInstallationBase();
+
+   @Nullable
+   public abstract Types.OSFamliyType osFamily();
+
+   @Nullable
+   public abstract String os();
+
+   @Nullable
+   public abstract String osVersion();
+
+   public abstract int osArchitecture();
+
+   @Nullable
+   public abstract Types.OSImageType osImageType();
+
+   public abstract int minHddSize();
+
+   @Nullable
+   public abstract Types.ApplianceType type();
+
+   @Nullable
+   public abstract String state();
+
+   @Nullable
+   public abstract String version();
+
+   @Nullable
+   public abstract List<String> categories();
+
+   @Nullable
+   public abstract String eulaUrl();
+
+   @SerializedNames({"id", "name", "available_datacenters", 
"os_installation_base", "os_family", "os", "os_version", "os_architecture", 
"os_image_type",
+      "min_hdd_size", "type", "state", "version", "categories", "eula_url"})
+   public static SingleServerAppliance create(String id, String name, 
List<AvailableDataCenters> availableDataCenters, String osInstallationBase, 
Types.OSFamliyType osFamily, String os,
+           String osVersion, int osArchitecture, Types.OSImageType 
osImageType, int minHddSize, Types.ApplianceType type, String state, String 
version, List<String> categories, String eulaUrl) {
+      return builder()
+              .id(id)
+              .name(name)
+              .availableDataCenters(availableDataCenters == null ? 
ImmutableList.<AvailableDataCenters>of() : 
ImmutableList.copyOf(availableDataCenters))
+              .osInstallationBase(osInstallationBase)
+              .osFamily(osFamily)
+              .os(os)
+              .osVersion(osVersion)
+              .osArchitecture(osArchitecture)
+              .osImageType(osImageType)
+              .minHddSize(minHddSize)
+              .type(type)
+              .state(state)
+              .version(version)
+              .categories(categories == null ? ImmutableList.<String>of() : 
ImmutableList.copyOf(categories))
+              .eulaUrl(eulaUrl)
+              .build();
+   }
+
+   public static Builder builder() {
+      return new AutoValue_SingleServerAppliance.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+
+      public abstract Builder id(String id);
+
+      public abstract Builder name(String name);
+
+      public abstract Builder availableDataCenters(List<AvailableDataCenters> 
availableDataCenters);
+
+      public abstract Builder osInstallationBase(String osInstallationBase);
+
+      public abstract Builder osFamily(Types.OSFamliyType osFamily);
+
+      public abstract Builder os(String os);
+
+      public abstract Builder osVersion(String osVersion);
+
+      public abstract Builder osArchitecture(int osArchitecture);
+
+      public abstract Builder osImageType(Types.OSImageType osImageType);
+
+      public abstract Builder minHddSize(int minHddSize);
+
+      public abstract Builder type(Types.ApplianceType type);
+
+      public abstract Builder state(String state);
+
+      public abstract Builder version(String version);
+
+      public abstract Builder categories(List<String> categories);
+
+      public abstract Builder eulaUrl(String eulaUrl);
+
+      abstract List<String> categories();
+
+      abstract List<AvailableDataCenters> availableDataCenters();
+
+      abstract SingleServerAppliance autoBuild();
+
+      public SingleServerAppliance build() {
+         availableDataCenters(availableDataCenters() != null ? 
ImmutableList.copyOf(availableDataCenters()) : null);
+         categories(categories() != null ? ImmutableList.copyOf(categories()) 
: null);
+         return autoBuild();
+      }
+   }
+
+   @AutoValue
+   public abstract static class AvailableDataCenters {
+
+      public abstract String id();
+
+      public abstract String name();
+
+      @SerializedNames({"id", "name"})
+      public static AvailableDataCenters create(String id, String name) {
+         return new AutoValue_SingleServerAppliance_AvailableDataCenters(id, 
name);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Types.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Types.java 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Types.java
index 2228d59..903317c 100644
--- 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Types.java
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/domain/Types.java
@@ -242,4 +242,22 @@ public class Types {
          return Enums.getIfPresent(ProcessAlertType.class, v).or(UNRECOGNIZED);
       }
    }
+
+   public enum ApplianceType {
+
+      IMAGE, MY_IMAGE, ISO, Null, UNRECOGNIZED;
+
+      public static ApplianceType fromValue(String v) {
+         return Enums.getIfPresent(ApplianceType.class, v).or(UNRECOGNIZED);
+      }
+   }
+
+   public enum OSImageType {
+      Standard, Minimal, Personal, ISO_OS, ISO_TOOL, NULL, UNRECOGNIZED;
+
+      public static OSImageType fromValue(String v) {
+         return Enums.getIfPresent(OSImageType.class, v).or(UNRECOGNIZED);
+      }
+
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/eeaa3c66/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/exceptions/OneAndOneRateLimitExceededException.java
----------------------------------------------------------------------
diff --git 
a/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/exceptions/OneAndOneRateLimitExceededException.java
 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/exceptions/OneAndOneRateLimitExceededException.java
new file mode 100644
index 0000000..c0a0c9a
--- /dev/null
+++ 
b/oneandone/src/main/java/org/apache/jclouds/oneandone/rest/exceptions/OneAndOneRateLimitExceededException.java
@@ -0,0 +1,75 @@
+/*
+ * 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.oneandone.rest.exceptions;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import static 
org.apache.jclouds.oneandone.rest.handlers.OneAndOneRateLimitRetryHandler.millisUntilNextAvailableRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rest.RateLimitExceededException;
+
+public class OneAndOneRateLimitExceededException extends 
RateLimitExceededException {
+
+   private static final long serialVersionUID = 1L;
+   private static final String RATE_LIMIT_HEADER_PREFIX = "X-Rate-Limit-";
+
+   private Long timeToNextAvailableRequest;
+   private Integer remainingRequests;
+   private Integer averageRequestsAllowedPerMinute;
+
+   public OneAndOneRateLimitExceededException(HttpResponse response) {
+      super(response.getStatusLine() + "\n" + rateLimitHeaders(response));
+      parseRateLimitInfo(response);
+   }
+
+   public OneAndOneRateLimitExceededException(HttpResponse response, Throwable 
cause) {
+      super(response.getStatusLine() + "\n" + rateLimitHeaders(response), 
cause);
+      parseRateLimitInfo(response);
+   }
+
+   public Long timeToNextAvailableRequest() {
+      return timeToNextAvailableRequest;
+   }
+
+   public Integer remainingRequests() {
+      return remainingRequests;
+   }
+
+   public Integer averageRequestsAllowedPerMinute() {
+      return averageRequestsAllowedPerMinute;
+   }
+
+   private void parseRateLimitInfo(HttpResponse response) {
+      String reset = response.getFirstHeaderOrNull("X-Rate-Limit-Reset");
+      String remaining = 
response.getFirstHeaderOrNull("X-Rate-Limit-Remaining");
+      String limit = response.getFirstHeaderOrNull("X-Rate-Limit-Limit");
+
+      remainingRequests = remaining == null ? null : 
Integer.valueOf(remaining);
+      averageRequestsAllowedPerMinute = limit == null ? null : 
Integer.valueOf(limit);
+      timeToNextAvailableRequest = reset == null ? null : 
millisUntilNextAvailableRequest(Long.parseLong(reset));
+   }
+
+   private static Multimap<String, String> rateLimitHeaders(HttpResponse 
response) {
+      return Multimaps.filterKeys(response.getHeaders(), new 
Predicate<String>() {
+         @Override
+         public boolean apply(String input) {
+            return input.startsWith(RATE_LIMIT_HEADER_PREFIX);
+         }
+      });
+   }
+}

Reply via email to