From 9852aa6fca022595fd5d107ee2624c5aa9288952 Mon Sep 17 00:00:00 2001 From: spasam Date: Tue, 12 Jul 2011 11:21:20 -0400 Subject: [PATCH] Implented vApp tag support for Terremark Enterprise. Also added configurable exponential delay between automatic retries. --- .../vcloud/domain/VCloudExpressVApp.java | 2 + .../internal/VCloudExpressVAppImpl.java | 24 ++++++- .../vcloud/xml/VCloudExpressVAppHandler.java | 11 ++- core/src/main/java/org/jclouds/Constants.java | 9 +++ .../java/org/jclouds/PropertiesBuilder.java | 9 +++ .../jclouds/concurrent/FutureIterables.java | 8 ++- .../handlers/BackoffLimitedRetryHandler.java | 6 +- providers/trmk-ecloud/pom.xml | 2 +- .../terremark/TerremarkECloudAsyncClient.java | 12 ++++ .../terremark/TerremarkECloudClient.java | 8 +++ .../terremark/TerremarkECloudMediaType.java | 19 ++++-- .../TerremarkECloudPropertiesBuilder.java | 4 +- .../TerremarkECloudAsyncClientTest.java | 28 ++++++-- .../src/test/resources/catalog-ecloud.xml | 68 +++++++++---------- 14 files changed, 155 insertions(+), 55 deletions(-) diff --git a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/domain/VCloudExpressVApp.java b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/domain/VCloudExpressVApp.java index c06817403f..1f33b96bd5 100644 --- a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/domain/VCloudExpressVApp.java +++ b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/domain/VCloudExpressVApp.java @@ -40,6 +40,8 @@ import com.google.inject.ImplementedBy; public interface VCloudExpressVApp extends ReferenceType { ReferenceType getVDC(); + Set getExtendedInfo(); + Status getStatus(); Long getSize(); diff --git a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/domain/internal/VCloudExpressVAppImpl.java b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/domain/internal/VCloudExpressVAppImpl.java index afbcbb51e0..4e4a7c6b7f 100644 --- a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/domain/internal/VCloudExpressVAppImpl.java +++ b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/domain/internal/VCloudExpressVAppImpl.java @@ -21,6 +21,7 @@ package org.jclouds.vcloud.domain.internal; import static com.google.common.base.Preconditions.checkNotNull; import java.net.URI; +import java.util.HashSet; import java.util.Set; import org.jclouds.cim.ResourceAllocationSettingData; @@ -41,6 +42,7 @@ public class VCloudExpressVAppImpl implements VCloudExpressVApp { private final String name; private final URI href; private final ReferenceType vDC; + private final Set extendedInfo; private final Status status; private final Long size; private final ListMultimap networkToAddresses; @@ -55,6 +57,14 @@ public class VCloudExpressVAppImpl implements VCloudExpressVApp { public VCloudExpressVAppImpl(String name, URI href, Status status, Long size, ReferenceType vDC, ListMultimap networkToAddresses, Integer osType, String operatingSystemDescription, VirtualSystemSettingData system, Set resourceAllocations) { + this(name, href, status, size, vDC, networkToAddresses, osType, operatingSystemDescription, system, + resourceAllocations, new HashSet()); + } + + public VCloudExpressVAppImpl(String name, URI href, Status status, Long size, ReferenceType vDC, + ListMultimap networkToAddresses, Integer osType, String operatingSystemDescription, + VirtualSystemSettingData system, Set resourceAllocations, + Set extendedInfo) { this.name = checkNotNull(name, "name"); this.href = checkNotNull(href, "href"); this.status = checkNotNull(status, "status"); @@ -65,6 +75,7 @@ public class VCloudExpressVAppImpl implements VCloudExpressVApp { this.operatingSystemDescription = operatingSystemDescription; this.system = system; this.resourceAllocations = checkNotNull(resourceAllocations, "resourceAllocations"); + this.extendedInfo = extendedInfo; } @Override @@ -102,6 +113,11 @@ public class VCloudExpressVAppImpl implements VCloudExpressVApp { return vDC; } + @Override + public Set getExtendedInfo() { + return extendedInfo; + } + @Override public int hashCode() { final int prime = 31; @@ -116,6 +132,7 @@ public class VCloudExpressVAppImpl implements VCloudExpressVApp { result = prime * result + ((status == null) ? 0 : status.hashCode()); result = prime * result + ((system == null) ? 0 : system.hashCode()); result = prime * result + ((vDC == null) ? 0 : vDC.hashCode()); + result = prime * result + ((extendedInfo == null) ? 0 : extendedInfo.hashCode()); return result; } @@ -178,6 +195,11 @@ public class VCloudExpressVAppImpl implements VCloudExpressVApp { return false; } else if (!vDC.equals(other.vDC)) return false; + if (extendedInfo == null) { + if (other.extendedInfo != null) + return false; + } else if (!extendedInfo.equals(other.extendedInfo)) + return false; return true; } @@ -201,7 +223,7 @@ public class VCloudExpressVAppImpl implements VCloudExpressVApp { return "[href=" + href + ", name=" + name + ", networkToAddresses=" + networkToAddresses + ", osType=" + osType + ", operatingSystemDescription=" + operatingSystemDescription + ", resourceAllocationByType=" + resourceAllocations + ", size=" + size + ", status=" + status + ", system=" + system + ", vDC=" + vDC - + "]"; + + ", extendedInfo=" + extendedInfo + "]"; } @Override diff --git a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/xml/VCloudExpressVAppHandler.java b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/xml/VCloudExpressVAppHandler.java index 0f9a672496..341ffbe93b 100644 --- a/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/xml/VCloudExpressVAppHandler.java +++ b/apis/vcloudexpress/src/main/java/org/jclouds/vcloud/xml/VCloudExpressVAppHandler.java @@ -79,10 +79,11 @@ public class VCloudExpressVAppHandler extends ParseSax.HandlerWithResult extendedInfo = Sets.newLinkedHashSet(); public VCloudExpressVApp getResult() { return new VCloudExpressVAppImpl(name, location, status, size, vDC, networkToAddresses, osType, - operatingSystemDescription, system, allocations); + operatingSystemDescription, system, allocations, extendedInfo); } public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { @@ -99,8 +100,12 @@ public class VCloudExpressVAppHandler extends ParseSax.HandlerWithResult + * Commands are retried, if the problem on the server side was a resolvable conflict. However, + * the maximum tries of a single command is bounded. If {@link #PROPERTY_MAX_RETRIES} is greater + * than zero, this property is used to determine the start delay. The delay is based on exponential + * backoff algorithm. Default value for this property is 50 milliseconds. + */ + public static final String PROPERTY_RETRY_DELAY_START = "jclouds.retries-delay-start"; /** * Integer property. *

diff --git a/core/src/main/java/org/jclouds/PropertiesBuilder.java b/core/src/main/java/org/jclouds/PropertiesBuilder.java index c575e6dbd8..a29f34afd8 100644 --- a/core/src/main/java/org/jclouds/PropertiesBuilder.java +++ b/core/src/main/java/org/jclouds/PropertiesBuilder.java @@ -38,6 +38,7 @@ import static org.jclouds.Constants.PROPERTY_PROXY_PORT; import static org.jclouds.Constants.PROPERTY_PROXY_SYSTEM; import static org.jclouds.Constants.PROPERTY_PROXY_USER; import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME; +import static org.jclouds.Constants.PROPERTY_RETRY_DELAY_START; import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; import static org.jclouds.Constants.PROPERTY_SO_TIMEOUT; import static org.jclouds.Constants.PROPERTY_TRUST_ALL_CERTS; @@ -137,6 +138,14 @@ public class PropertiesBuilder { return this; } + /** + * @see org.jclouds.Constants.PROPERTY_RETRY_DELAY_START + */ + public PropertiesBuilder withRetriesDelayStart(long delayStart) { + properties.setProperty(PROPERTY_RETRY_DELAY_START, Long.toString(delayStart)); + return this; + } + /** * @see org.jclouds.Constants.PROPERTY_MAX_REDIRECTS */ diff --git a/core/src/main/java/org/jclouds/concurrent/FutureIterables.java b/core/src/main/java/org/jclouds/concurrent/FutureIterables.java index 2540950acd..d1976d4485 100644 --- a/core/src/main/java/org/jclouds/concurrent/FutureIterables.java +++ b/core/src/main/java/org/jclouds/concurrent/FutureIterables.java @@ -59,6 +59,10 @@ public class FutureIterables { @Named(Constants.PROPERTY_MAX_RETRIES) private static int maxRetries = 5; + @Inject(optional = true) + @Named(Constants.PROPERTY_RETRY_DELAY_START) + private static long delayStart = 50L; + @Inject(optional = true) private static BackoffLimitedRetryHandler retryHandler = BackoffLimitedRetryHandler.INSTANCE; @@ -91,8 +95,8 @@ public class FutureIterables { exceptions = awaitCompletion(responses, exec, maxTime, logger, logPrefix); if (exceptions.size() > 0) { fromIterable = exceptions.keySet(); - retryHandler.imposeBackoffExponentialDelay(i + 1, String.format("error %s: %s: %s", logPrefix, - fromIterable, exceptions)); + retryHandler.imposeBackoffExponentialDelay(delayStart, 2, i + 1, maxRetries, + String.format("error %s: %s: %s", logPrefix, fromIterable, exceptions)); } else { break; } diff --git a/core/src/main/java/org/jclouds/http/handlers/BackoffLimitedRetryHandler.java b/core/src/main/java/org/jclouds/http/handlers/BackoffLimitedRetryHandler.java index 606dc0e8db..51940d1808 100644 --- a/core/src/main/java/org/jclouds/http/handlers/BackoffLimitedRetryHandler.java +++ b/core/src/main/java/org/jclouds/http/handlers/BackoffLimitedRetryHandler.java @@ -86,6 +86,10 @@ public class BackoffLimitedRetryHandler implements HttpRetryHandler, IOException @Named(Constants.PROPERTY_MAX_RETRIES) private int retryCountLimit = 5; + @Inject(optional = true) + @Named(Constants.PROPERTY_RETRY_DELAY_START) + private long delayStart = 50L; + @Resource protected Logger logger = Logger.NULL; @@ -115,7 +119,7 @@ public class BackoffLimitedRetryHandler implements HttpRetryHandler, IOException } public void imposeBackoffExponentialDelay(int failureCount, String commandDescription) { - imposeBackoffExponentialDelay(50L, 2, failureCount, retryCountLimit, commandDescription); + imposeBackoffExponentialDelay(delayStart, 2, failureCount, retryCountLimit, commandDescription); } public void imposeBackoffExponentialDelay(long period, int pow, int failureCount, int max, String commandDescription) { diff --git a/providers/trmk-ecloud/pom.xml b/providers/trmk-ecloud/pom.xml index 52e69bb1a4..6dc39c5b72 100644 --- a/providers/trmk-ecloud/pom.xml +++ b/providers/trmk-ecloud/pom.xml @@ -36,7 +36,7 @@ https://services.enterprisecloud.terremark.com/api - 0.8b-ext2.7 + 0.8b-ext2.8 FIXME FIXME diff --git a/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClient.java b/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClient.java index f1c636f6c8..76ddf1c302 100644 --- a/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClient.java +++ b/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClient.java @@ -25,6 +25,7 @@ import static org.jclouds.vcloud.terremark.TerremarkECloudMediaType.INTERNETSERV import static org.jclouds.vcloud.terremark.TerremarkECloudMediaType.IPADDRESS_LIST_XML; import static org.jclouds.vcloud.terremark.TerremarkECloudMediaType.KEYSLIST_XML; import static org.jclouds.vcloud.terremark.TerremarkECloudMediaType.PUBLICIP_XML; +import static org.jclouds.vcloud.terremark.TerremarkECloudMediaType.VAPPEXTINFO_XML; import java.net.URI; import java.util.Set; @@ -55,6 +56,7 @@ import org.jclouds.vcloud.terremark.domain.KeyPair; import org.jclouds.vcloud.terremark.domain.Protocol; import org.jclouds.vcloud.terremark.domain.PublicIpAddress; import org.jclouds.vcloud.terremark.domain.TerremarkNetwork; +import org.jclouds.vcloud.terremark.domain.VAppExtendedInfo; import org.jclouds.vcloud.terremark.domain.TerremarkOrgNetwork; import org.jclouds.vcloud.terremark.functions.OrgURIToKeysListEndpoint; import org.jclouds.vcloud.terremark.functions.VDCURIToInternetServicesEndpoint; @@ -69,6 +71,7 @@ import org.jclouds.vcloud.terremark.xml.KeyPairsHandler; import org.jclouds.vcloud.terremark.xml.PublicIpAddressesHandler; import org.jclouds.vcloud.terremark.xml.TerremarkNetworkHandler; import org.jclouds.vcloud.terremark.xml.TerremarkOrgNetworkFromTerremarkVCloudExpressNetworkHandler; +import org.jclouds.vcloud.terremark.xml.VAppExtendedInfoHandler; import com.google.common.util.concurrent.ListenableFuture; @@ -250,4 +253,13 @@ public interface TerremarkECloudAsyncClient extends TerremarkVCloudAsyncClient { @XMLResponseParser(IpAddressesHandler.class) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) ListenableFuture> getIpAddresses(@EndpointParam URI network); + + /** + * @see TerremarkVCloudExpressClient#getInternetService + */ + @GET + @Consumes(VAPPEXTINFO_XML) + @XMLResponseParser(VAppExtendedInfoHandler.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVAppExtendedInfo(@EndpointParam URI href); } diff --git a/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudClient.java b/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudClient.java index e57e145aef..cef87694cc 100644 --- a/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudClient.java +++ b/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudClient.java @@ -29,6 +29,7 @@ import org.jclouds.vcloud.terremark.domain.IpAddress; import org.jclouds.vcloud.terremark.domain.PublicIpAddress; import org.jclouds.vcloud.terremark.domain.TerremarkNetwork; import org.jclouds.vcloud.terremark.domain.TerremarkOrgNetwork; +import org.jclouds.vcloud.terremark.domain.VAppExtendedInfo; /** * Provides access to VCloud resources via their REST API. @@ -58,4 +59,11 @@ public interface TerremarkECloudClient extends TerremarkVCloudClient { Set getIpAddresses(URI network); + /** + * Returns extended information for the vApp. + * + * @param vApp The URI at which the vApp information is available. + * @return Extended vApp information like tags, long name, network adapter information. + */ + VAppExtendedInfo getVAppExtendedInfo(URI href); } diff --git a/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudMediaType.java b/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudMediaType.java index 12aff66d17..95f527b3e3 100644 --- a/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudMediaType.java +++ b/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudMediaType.java @@ -22,7 +22,7 @@ import javax.ws.rs.core.MediaType; /** * Resource Types used in Terremark eCloud - * + * * @see MediaType */ public interface TerremarkECloudMediaType extends TerremarkVCloudMediaType { @@ -35,7 +35,7 @@ public interface TerremarkECloudMediaType extends TerremarkVCloudMediaType { * "application/vnd.tmrk.ecloud.publicIp+xml" */ public final static MediaType PUBLICIP_XML_TYPE = new MediaType("application", "vnd.tmrk.ecloud.publicIp+xml"); - + /** * "application/vnd.tmrk.ecloud.internetService+xml" */ @@ -66,15 +66,24 @@ public interface TerremarkECloudMediaType extends TerremarkVCloudMediaType { * "application/vnd.tmrk.ecloud.keysList+xml" */ public final static MediaType KEYSLIST_XML_TYPE = new MediaType("application", "vnd.tmrk.ecloud.keysList+xml"); - - + /** * "application/vnd.tmrk.ecloud.ipAddressList+xml" */ public final static String IPADDRESS_LIST_XML = "application/vnd.tmrk.ecloud.ipAddressList+xml"; - + /** * "application/vnd.tmrk.ecloud.ipAddressList+xml" */ public final static MediaType IPADDRESSES_LIST_XML_TYPE = new MediaType("application", "vnd.tmrk.ecloud.ipAddressList+xml"); + + /** + * "application/vnd.tmrk.ecloud.vApp+xml" + */ + public final static String VAPPEXTINFO_XML = "application/vnd.tmrk.ecloud.vApp+xml"; + + /** + * "application/vnd.tmrk.ecloud.vApp+xml" + */ + public final static MediaType VAPPEXTINFO_XML_TYPE = new MediaType("application", "vnd.tmrk.ecloud.vApp+xml"); } diff --git a/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudPropertiesBuilder.java b/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudPropertiesBuilder.java index f5c256d726..129f404f68 100644 --- a/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudPropertiesBuilder.java +++ b/providers/trmk-ecloud/src/main/java/org/jclouds/vcloud/terremark/TerremarkECloudPropertiesBuilder.java @@ -38,10 +38,10 @@ public class TerremarkECloudPropertiesBuilder extends TerremarkVCloudPropertiesB protected Properties defaultProperties() { Properties properties = super.defaultProperties(); properties.setProperty(PROPERTY_ISO3166_CODES, "US-FL,NL-NH"); - properties.setProperty(PROPERTY_API_VERSION, "0.8b-ext2.7"); + properties.setProperty(PROPERTY_API_VERSION, "0.8b-ext2.8"); properties.setProperty(PROPERTY_ENDPOINT, "https://services.enterprisecloud.terremark.com/api"); properties.setProperty(PROPERTY_TERREMARK_EXTENSION_NAME, "eCloudExtensions"); - properties.setProperty(PROPERTY_TERREMARK_EXTENSION_VERSION, "2.7"); + properties.setProperty(PROPERTY_TERREMARK_EXTENSION_VERSION, "2.8"); // default for ubuntu properties.setProperty(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED, 360l * 1000l + ""); // ubuntu image has a problem with sftp diff --git a/providers/trmk-ecloud/src/test/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClientTest.java b/providers/trmk-ecloud/src/test/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClientTest.java index 5fc7bb4e75..808eb5acf8 100644 --- a/providers/trmk-ecloud/src/test/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClientTest.java +++ b/providers/trmk-ecloud/src/test/java/org/jclouds/vcloud/terremark/TerremarkECloudAsyncClientTest.java @@ -82,6 +82,7 @@ import org.jclouds.vcloud.terremark.xml.NodesHandler; import org.jclouds.vcloud.terremark.xml.PublicIpAddressesHandler; import org.jclouds.vcloud.terremark.xml.TerremarkOrgNetworkFromTerremarkVCloudExpressNetworkHandler; import org.jclouds.vcloud.terremark.xml.TerremarkVDCHandler; +import org.jclouds.vcloud.terremark.xml.VAppExtendedInfoHandler; import org.jclouds.vcloud.xml.VCloudExpressCatalogHandler; import org.jclouds.vcloud.xml.VCloudExpressVAppHandler; import org.testng.annotations.Test; @@ -308,7 +309,7 @@ public class TerremarkECloudAsyncClientTest extends RestClientTestnametrueeggs", + "nametrueeggs", "application/vnd.tmrk.vCloud.nodeService+xml", false); assertResponseParserClassEquals(method, request, ParseSax.class); assertSaxResponseParserClassEquals(method, NodeHandler.class); @@ -422,7 +423,7 @@ public class TerremarkECloudAsyncClientTest extends RestClientTestnametrue", + "nametrue", "application/vnd.tmrk.vCloud.nodeService+xml", false); assertResponseParserClassEquals(method, request, ParseSax.class); assertSaxResponseParserClassEquals(method, NodeHandler.class); @@ -544,6 +545,21 @@ public class TerremarkECloudAsyncClientTest extends RestClientTest - \ No newline at end of file +