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); + } + }); + } +}
