Issue 327: added URI option for getting VDC

This commit is contained in:
Adrian Cole 2010-08-08 14:33:15 -07:00
parent 7e5fb14f60
commit 7f38672a4c
5 changed files with 175 additions and 59 deletions

View File

@ -28,6 +28,8 @@ import static org.jclouds.vcloud.VCloudMediaType.VAPPTEMPLATE_XML;
import static org.jclouds.vcloud.VCloudMediaType.VAPP_XML;
import static org.jclouds.vcloud.VCloudMediaType.VDC_XML;
import java.net.URI;
import javax.annotation.Nullable;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -184,8 +186,9 @@ public interface VCloudAsyncClient {
ListenableFuture<? extends VDC> getDefaultVDC();
/**
* @see VCloudClient#getVDC
* @see VCloudClient#getVDC(String)
*/
@Deprecated
@GET
@Endpoint(org.jclouds.vcloud.endpoints.VCloudApi.class)
@Path("/vdc/{vDCId}")
@ -194,6 +197,15 @@ public interface VCloudAsyncClient {
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends VDC> getVDC(@PathParam("vDCId") String vDCId);
/**
* @see VCloudClient#getVDC(URI)
*/
@GET
@XMLResponseParser(VDCHandler.class)
@Consumes(VDC_XML)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<? extends VDC> getVDC(@EndpointParam URI vDCId);
/**
* @see VCloudClient#getTasksList
*/

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.vcloud;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
@ -37,8 +38,7 @@ import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
* Provides access to VCloud resources via their REST API.
* <p/>
*
* @see <a href="https://community.vcloudexpress.terremark.com/en-us/discussion_forums/f/60.aspx"
* />
* @see <a href="https://community.vcloudexpress.terremark.com/en-us/discussion_forums/f/60.aspx" />
* @author Adrian Cole
*/
@Timeout(duration = 300, timeUnit = TimeUnit.SECONDS)
@ -56,8 +56,8 @@ public interface VCloudClient {
Organization getOrganization(String orgId);
/**
* This call returns a list of all vCloud Data Centers (vdcs), catalogs, and
* task lists within the organization.
* This call returns a list of all vCloud Data Centers (vdcs), catalogs, and task lists within
* the organization.
*
* @param name
* organization name, or null for the default
@ -74,8 +74,14 @@ public interface VCloudClient {
Network getNetwork(String networkId);
/**
* please use {@link #getVDC(URI)}
*/
@Deprecated
VDC getVDC(String vDCId);
VDC getVDC(URI vdc);
VDC getDefaultVDC();
TasksList getTasksList(String tasksListId);
@ -89,14 +95,12 @@ public interface VCloudClient {
Task undeployVApp(String vAppId);
/**
* This call powers on the vApp, as specified in the vApp's ovf:Startup
* element.
* This call powers on the vApp, as specified in the vApp's ovf:Startup element.
*/
Task powerOnVApp(String vAppId);
/**
* This call powers off the vApp, as specified in the vApp's ovf:Startup
* element.
* This call powers off the vApp, as specified in the vApp's ovf:Startup element.
*/
Task powerOffVApp(String vAppId);
@ -122,7 +126,7 @@ public interface VCloudClient {
VApp getVApp(String appId);
VApp instantiateVAppTemplateInVDC(String vDCId, String appName, String templateId,
InstantiateVAppTemplateOptions... options);
InstantiateVAppTemplateOptions... options);
Task cloneVAppInVDC(String vDCId, String vAppIdToClone, String newName, CloneVAppOptions... options);
}

View File

@ -29,6 +29,7 @@ import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_TIMEO
import java.net.URI;
import java.util.Map;
import java.util.SortedMap;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -81,15 +82,14 @@ import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
* Configures the VCloud authentication service connection, including logging
* and http transport.
* Configures the VCloud authentication service connection, including logging and http transport.
*
* @author Adrian Cole
*/
@RequiresHttp
@ConfiguresRestClient
public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A extends VCloudAsyncClient> extends
RestClientModule<S, A> {
RestClientModule<S, A> {
public BaseVCloudRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
super(syncClientType, asyncClientType);
@ -110,7 +110,7 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
protected Predicate<String> successTester(TaskSuccess success,
@Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) {
@Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) {
return new RetryablePredicate<String>(success, completed);
}
@ -135,16 +135,43 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
}
@Provides
@Named("VDC_TO_ORG")
@Singleton
protected Map<String, String> provideVDCtoORG(@Org Iterable<NamedResource> orgs, VCloudClient client) {
Map<String, String> returnVal = Maps.newLinkedHashMap();
for (NamedResource orgr : orgs) {
for (NamedResource vdc : client.getOrganizationNamed(orgr.getName()).getVDCs().values()) {
returnVal.put(vdc.getId(), orgr.getName());
}
}
return returnVal;
@VDC
protected Supplier<Map<String, String>> provideVDCtoORG(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final @VDC Supplier<Map<String, Map<String, NamedResource>>> orgToVDCSupplier) {
return Suppliers.memoizeWithExpiration(new RetryOnTimeOutExceptionSupplier<Map<String, String>>(
new Supplier<Map<String, String>>() {
public Map<String, String> get() {
// http://code.google.com/p/google-guice/issues/detail?id=483
// guice doesn't remember when singleton providers throw
// exceptions.
// in this case, if describeRegions fails, it is called
// again for
// each provider method that depends on it. To
// short-circuit this,
// we remember the last exception trusting that guice is
// single-threaded
if (authException != null)
throw authException;
try {
Map<String, String> returnVal = Maps.newLinkedHashMap();
for (Entry<String, Map<String, NamedResource>> orgr : orgToVDCSupplier.get().entrySet()) {
for (String vdc : orgr.getValue().keySet()) {
returnVal.put(vdc, orgr.getKey());
}
}
return returnVal;
} catch (AuthorizationException e) {
authException = e;
throw e;
} catch (Exception e) {
Throwables.propagate(e);
assert false : e;
return null;
}
}
}), seconds, TimeUnit.SECONDS);
}
@Provides
@ -168,41 +195,99 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
protected Supplier<VCloudSession> provideVCloudTokenCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final VCloudLoginAsyncClient login) {
final VCloudLoginAsyncClient login) {
return Suppliers.memoizeWithExpiration(new RetryOnTimeOutExceptionSupplier<VCloudSession>(
new Supplier<VCloudSession>() {
public VCloudSession get() {
// http://code.google.com/p/google-guice/issues/detail?id=483
// guice doesn't remember when singleton providers throw
// exceptions.
// in this case, if describeRegions fails, it is called
// again for
// each provider method that depends on it. To
// short-circuit this,
// we remember the last exception trusting that guice is
// single-threaded
if (authException != null)
throw authException;
try {
return login.login().get(10, TimeUnit.SECONDS);
} catch (AuthorizationException e) {
BaseVCloudRestClientModule.this.authException = e;
throw e;
} catch (Exception e) {
Throwables.propagate(e);
assert false : e;
return null;
new Supplier<VCloudSession>() {
public VCloudSession get() {
// http://code.google.com/p/google-guice/issues/detail?id=483
// guice doesn't remember when singleton providers throw
// exceptions.
// in this case, if describeRegions fails, it is called
// again for
// each provider method that depends on it. To
// short-circuit this,
// we remember the last exception trusting that guice is
// single-threaded
if (authException != null)
throw authException;
try {
return login.login().get(10, TimeUnit.SECONDS);
} catch (AuthorizationException e) {
BaseVCloudRestClientModule.this.authException = e;
throw e;
} catch (Exception e) {
Throwables.propagate(e);
assert false : e;
return null;
}
}
}
}), seconds, TimeUnit.SECONDS);
}), seconds, TimeUnit.SECONDS);
}
@Provides
@Singleton
@VDC
protected Supplier<Map<String, Map<String, NamedResource>>> provideOrgToVDCCache(
@Named(PROPERTY_SESSION_INTERVAL) long seconds, final OrgNameToVDCSupplier supplier) {
return Suppliers.memoizeWithExpiration(
new RetryOnTimeOutExceptionSupplier<Map<String, Map<String, NamedResource>>>(
new Supplier<Map<String, Map<String, NamedResource>>>() {
public Map<String, Map<String, NamedResource>> get() {
// http://code.google.com/p/google-guice/issues/detail?id=483
// guice doesn't remember when singleton providers throw
// exceptions.
// in this case, if describeRegions fails, it is called
// again for
// each provider method that depends on it. To
// short-circuit this,
// we remember the last exception trusting that guice is
// single-threaded
if (authException != null)
throw authException;
try {
return supplier.get();
} catch (AuthorizationException e) {
authException = e;
throw e;
} catch (Exception e) {
Throwables.propagate(e);
assert false : e;
return null;
}
}
}), seconds, TimeUnit.SECONDS);
}
@Singleton
public static class OrgNameToVDCSupplier implements Supplier<Map<String, Map<String, NamedResource>>> {
protected final Supplier<VCloudSession> sessionSupplier;
private final VCloudClient client;
@Inject
protected OrgNameToVDCSupplier(Supplier<VCloudSession> sessionSupplier, VCloudClient client) {
this.sessionSupplier = sessionSupplier;
this.client = client;
}
@Override
public Map<String, Map<String, NamedResource>> get() {
Map<String, Map<String, NamedResource>> returnVal = Maps.newLinkedHashMap();
for (String orgName : sessionSupplier.get().getOrgs().keySet()) {
returnVal.put(orgName, client.getOrganizationNamed(orgName).getVDCs());
}
return returnVal;
}
}
@Provides
@Singleton
@org.jclouds.vcloud.endpoints.VCloudLogin
protected URI provideAuthenticationURI(VCloudVersionsAsyncClient versionService,
@Named(PROPERTY_API_VERSION) String version) throws InterruptedException, ExecutionException, TimeoutException {
@Named(PROPERTY_API_VERSION) String version) throws InterruptedException, ExecutionException,
TimeoutException {
SortedMap<String, URI> versions = versionService.getSupportedVersions().get(180, TimeUnit.SECONDS);
checkState(versions.size() > 0, "No versions present");
checkState(versions.containsKey(version), "version " + version + " not present in: " + versions);
@ -262,7 +347,7 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
protected Organization provideOrganization(VCloudClient discovery) throws ExecutionException, TimeoutException,
InterruptedException {
InterruptedException {
if (authException != null)
throw authException;
try {
@ -293,7 +378,7 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Network
@Singleton
protected URI provideDefaultNetwork(VCloudClient client) throws InterruptedException, ExecutionException,
TimeoutException {
TimeoutException {
if (authException != null)
throw authException;
try {

View File

@ -306,7 +306,7 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
checkFilters(request);
}
public void testGetVDC() throws SecurityException, NoSuchMethodException, IOException {
public void testGetVDCString() throws SecurityException, NoSuchMethodException, IOException {
Method method = VCloudAsyncClient.class.getMethod("getVDC", String.class);
HttpRequest request = processor.createRequest(method, "1");
@ -321,6 +321,21 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
checkFilters(request);
}
public void testGetVDCURI() throws SecurityException, NoSuchMethodException, IOException {
Method method = VCloudAsyncClient.class.getMethod("getVDC", URI.class);
HttpRequest request = processor.createRequest(method, URI.create("https://vcloud.safesecureweb.com/api/v0.8/vdc/1"));
assertRequestLineEquals(request, "GET https://vcloud.safesecureweb.com/api/v0.8/vdc/1 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/vnd.vmware.vcloud.vdc+xml\n");
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, VDCHandler.class);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(request);
}
public void testGetDefaultTasksList() throws SecurityException, NoSuchMethodException, IOException {
Method method = VCloudAsyncClient.class.getMethod("getDefaultTasksList");
HttpRequest request = processor.createRequest(method);

View File

@ -28,9 +28,11 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.endpoints.VDC;
import org.jclouds.vcloud.terremark.compute.domain.OrgAndName;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
/**
*
@ -38,27 +40,25 @@ import com.google.common.base.Function;
*
*/
@Singleton
public class NodeMetadataToOrgAndName implements
Function<NodeMetadata, OrgAndName> {
public class NodeMetadataToOrgAndName implements Function<NodeMetadata, OrgAndName> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
final Map<String, String> vdcToOrg;
final Supplier<Map<String, String>> vdcToOrg;
@Inject
NodeMetadataToOrgAndName(@Named("VDC_TO_ORG") Map<String, String> vdcToOrg) {
NodeMetadataToOrgAndName(@VDC Supplier<Map<String, String>> vdcToOrg) {
this.vdcToOrg = vdcToOrg;
}
@Override
public OrgAndName apply(NodeMetadata from) {
if (from.getTag() != null) {
String org = vdcToOrg.get(from.getLocation().getId());
String org = vdcToOrg.get().get(from.getLocation().getId());
if (org == null) {
logger.warn("did not find an association for vdc %s in %s", from
.getLocation().getId(), vdcToOrg);
logger.warn("did not find an association for vdc %s in %s", from.getLocation().getId(), vdcToOrg);
} else {
return new OrgAndName(org, from.getTag());
}