Repository: jclouds-labs Updated Branches: refs/heads/2.0.x b151914f0 -> c1d36ce79
JCLOUDS-1210: Implement the ImageExtension in ProfitBricks REST Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/c1d36ce7 Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/c1d36ce7 Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/c1d36ce7 Branch: refs/heads/2.0.x Commit: c1d36ce7910f8de278e4375889be7dadd0278d96 Parents: b151914 Author: Ali Bazlamit <[email protected]> Authored: Tue Mar 7 19:48:12 2017 +0100 Committer: Ignasi Barrera <[email protected]> Committed: Tue Mar 7 21:26:51 2017 +0100 ---------------------------------------------------------------------- .../ProfitBricksComputeServiceAdapter.java | 2 +- ...ProfitBricksComputeServiceContextModule.java | 9 +- .../extensions/ProfitBricksImageExtension.java | 141 +++++++++++++++++++ .../ProfitBricksTemplateBuilderLiveTest.java | 2 - .../ProfitBricksImageExtensionLiveTest.java | 46 ++++++ .../rest/features/IpblockApiLiveTest.java | 3 +- 6 files changed, 196 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c1d36ce7/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceAdapter.java ---------------------------------------------------------------------- diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceAdapter.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceAdapter.java index 0f15123..4c79640 100644 --- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceAdapter.java +++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksComputeServiceAdapter.java @@ -438,7 +438,7 @@ public class ProfitBricksComputeServiceAdapter implements ComputeServiceAdapter< logger.trace(">> found snapshot [%s]", snapshot.properties().name()); return snapshot; } - throw new ResourceNotFoundException("No image/snapshot with id '" + id + "' was found"); + return null; } @Override http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c1d36ce7/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/config/ProfitBricksComputeServiceContextModule.java ---------------------------------------------------------------------- diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/config/ProfitBricksComputeServiceContextModule.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/config/ProfitBricksComputeServiceContextModule.java index b244fb2..a144418 100644 --- a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/config/ProfitBricksComputeServiceContextModule.java +++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/config/ProfitBricksComputeServiceContextModule.java @@ -32,6 +32,7 @@ import org.apache.jclouds.profitbricks.rest.ProfitBricksApi; import org.apache.jclouds.profitbricks.rest.compute.ProfitBricksComputeServiceAdapter; import org.apache.jclouds.profitbricks.rest.compute.concurrent.ProvisioningJob; import org.apache.jclouds.profitbricks.rest.compute.concurrent.ProvisioningManager; +import org.apache.jclouds.profitbricks.rest.compute.extensions.ProfitBricksImageExtension; import org.apache.jclouds.profitbricks.rest.compute.function.ProvisionableToImage; import org.apache.jclouds.profitbricks.rest.compute.function.ServerInDataCenterToNodeMetadata; import org.apache.jclouds.profitbricks.rest.compute.function.VolumeToVolume; @@ -62,6 +63,7 @@ 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.extensions.ImageExtension; import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet; import org.jclouds.domain.Location; import org.jclouds.functions.IdentityFunction; @@ -86,9 +88,9 @@ public class ProfitBricksComputeServiceContextModule extends bind(new TypeLiteral<ComputeServiceAdapter<ServerInDataCenter, Hardware, Provisionable, Location>>() { }).to(ProfitBricksComputeServiceAdapter.class); - + bind(TemplateBuilderImpl.class).to(ArbitraryCpuRamTemplateBuilderImpl.class); - + bind(new TypeLiteral<Function<ServerInDataCenter, NodeMetadata>>() { }).to(ServerInDataCenterToNodeMetadata.class); @@ -100,6 +102,9 @@ public class ProfitBricksComputeServiceContextModule extends bind(new TypeLiteral<Function<Hardware, Hardware>>() { }).to(Class.class.cast(IdentityFunction.class)); + + bind(new TypeLiteral<ImageExtension>() { + }).to(ProfitBricksImageExtension.class); } @Provides http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c1d36ce7/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/extensions/ProfitBricksImageExtension.java ---------------------------------------------------------------------- diff --git a/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/extensions/ProfitBricksImageExtension.java b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/extensions/ProfitBricksImageExtension.java new file mode 100644 index 0000000..2f55b4a --- /dev/null +++ b/profitbricks-rest/src/main/java/org/apache/jclouds/profitbricks/rest/compute/extensions/ProfitBricksImageExtension.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jclouds.profitbricks.rest.compute.extensions; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.Iterables; +import static com.google.common.collect.Iterables.find; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.UncheckedTimeoutException; +import java.net.URI; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import org.apache.jclouds.profitbricks.rest.ProfitBricksApi; +import static org.apache.jclouds.profitbricks.rest.config.ProfitBricksComputeProperties.POLL_PREDICATE_SNAPSHOT; +import org.apache.jclouds.profitbricks.rest.domain.Server; +import org.apache.jclouds.profitbricks.rest.domain.Snapshot; +import org.apache.jclouds.profitbricks.rest.domain.Volume; +import org.apache.jclouds.profitbricks.rest.domain.zonescoped.DataCenterAndId; +import org.apache.jclouds.profitbricks.rest.util.Trackables; +import org.jclouds.Constants; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.CloneImageTemplate; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.ImageTemplate; +import org.jclouds.compute.domain.ImageTemplateBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Location; +import static org.jclouds.location.predicates.LocationPredicates.idEquals; +import org.jclouds.logging.Logger; + +public class ProfitBricksImageExtension implements ImageExtension { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final ProfitBricksApi client; + private final ListeningExecutorService userExecutor; + private final Supplier<Set<? extends Location>> locations; + private final Predicate<String> snapshotAvailablePredicate; + private final Trackables trackables; + + @Inject + ProfitBricksImageExtension(ProfitBricksApi client, + @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, + @Memoized Supplier<Set<? extends Location>> locations, + @Named(POLL_PREDICATE_SNAPSHOT) Predicate<String> snapshotAvailablePredicate, + Trackables trackables) { + this.client = client; + this.userExecutor = userExecutor; + this.locations = locations; + this.snapshotAvailablePredicate = snapshotAvailablePredicate; + this.trackables = trackables; + } + + @Override + public ImageTemplate buildImageTemplateFromNode(String name, String id) { + DataCenterAndId datacenterAndId = DataCenterAndId.fromSlashEncoded(id); + Server server = client.serverApi().getServer(datacenterAndId.getDataCenter(), datacenterAndId.getId()); + if (server == null) { + throw new IllegalArgumentException("Cannot find server with id: " + id); + } + CloneImageTemplate template = new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name).build(); + return template; + } + + @Override + public ListenableFuture<Image> createImage(ImageTemplate template) { + final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; + final DataCenterAndId datacenterAndId = DataCenterAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId()); + + final Server server = client.serverApi().getServer(datacenterAndId.getDataCenter(), datacenterAndId.getId()); + List<Volume> volumes = client.volumeApi().getList(server.dataCenterId()); + + final Volume volume = Iterables.getOnlyElement(volumes); + + return userExecutor.submit(new Callable<Image>() { + @Override + public Image call() throws Exception { + Snapshot snapshot = client.volumeApi().createSnapshot(Volume.Request.createSnapshotBuilder() + .dataCenterId(datacenterAndId.getDataCenter()) + .volumeId(volume.id()) + .name(cloneTemplate.getName()) + .description(cloneTemplate.getName()) + .build()); + + trackables.waitUntilRequestCompleted(snapshot); + logger.info(">> Registered new snapshot %s, waiting for it to become available.", snapshot.id()); + + final Image image = new ImageBuilder() + .location(find(locations.get(), idEquals(snapshot.properties().location().getId()))) + .id(snapshot.id()) + .providerId(snapshot.id()) + .name(cloneTemplate.getName()) + .description(cloneTemplate.getName()) + .operatingSystem(OperatingSystem.builder().description(cloneTemplate.getName()).build()) + .status(Image.Status.PENDING).build(); + + if (snapshotAvailablePredicate.apply(image.getId())) { + return image; + } + throw new UncheckedTimeoutException("Image was not created within the time limit: " + image); + } + }); + } + + @Override + public boolean deleteImage(String id) { + try { + URI deleteJob = client.snapshotApi().delete(id); + trackables.waitUntilRequestCompleted(deleteJob); + return true; + } catch (Exception e) { + return false; + } + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c1d36ce7/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksTemplateBuilderLiveTest.java ---------------------------------------------------------------------- diff --git a/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksTemplateBuilderLiveTest.java b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksTemplateBuilderLiveTest.java index f029c41..a9c8d9d 100644 --- a/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksTemplateBuilderLiveTest.java +++ b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/ProfitBricksTemplateBuilderLiveTest.java @@ -18,9 +18,7 @@ package org.apache.jclouds.profitbricks.rest.compute; import com.google.common.collect.ImmutableSet; import com.google.inject.Module; - import java.util.Set; - import org.apache.jclouds.profitbricks.rest.config.ProfitBricksRateLimitModule; import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest; import org.testng.annotations.Test; http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c1d36ce7/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/extensions/ProfitBricksImageExtensionLiveTest.java ---------------------------------------------------------------------- diff --git a/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/extensions/ProfitBricksImageExtensionLiveTest.java b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/extensions/ProfitBricksImageExtensionLiveTest.java new file mode 100644 index 0000000..a492216 --- /dev/null +++ b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/compute/extensions/ProfitBricksImageExtensionLiveTest.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jclouds.profitbricks.rest.compute.extensions; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; +import org.apache.jclouds.profitbricks.rest.config.ProfitBricksRateLimitModule; +import org.jclouds.compute.extensions.internal.BaseImageExtensionLiveTest; +import org.jclouds.sshj.config.SshjSshClientModule; +import org.testng.annotations.Test; + +@Test(groups = "live", singleThreaded = true, testName = "ProfitBricksImageExtensionLiveTest") +public class ProfitBricksImageExtensionLiveTest extends BaseImageExtensionLiveTest { + + public ProfitBricksImageExtensionLiveTest() { + provider = "profitbricks-rest"; + } + + @Override + protected Iterable<Module> setupModules() { + ImmutableSet.Builder<Module> modules = ImmutableSet.builder(); + modules.addAll(super.setupModules()); + modules.add(new ProfitBricksRateLimitModule()); + return modules.build(); + } + + @Override + protected Module getSshModule() { + return new SshjSshClientModule(); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/c1d36ce7/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/features/IpblockApiLiveTest.java ---------------------------------------------------------------------- diff --git a/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/features/IpblockApiLiveTest.java b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/features/IpblockApiLiveTest.java index 5965f8c..6ecdfd3 100644 --- a/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/features/IpblockApiLiveTest.java +++ b/profitbricks-rest/src/test/java/org/apache/jclouds/profitbricks/rest/features/IpblockApiLiveTest.java @@ -17,7 +17,6 @@ package org.apache.jclouds.profitbricks.rest.features; import com.google.common.base.Predicate; - import java.net.URI; import java.util.List; import org.apache.jclouds.profitbricks.rest.domain.IpBlock; @@ -59,7 +58,7 @@ public class IpblockApiLiveTest extends BaseProfitBricksLiveTest { } @Test - public void testGetNic() { + public void testGet() { IpBlock ipBlock = ipBlockApi().get(testIpBlock.id()); assertNotNull(ipBlock);
