Issue 112: added better testing for cloud compatibility

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2290 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-11-15 01:48:27 +00:00
parent edf82a7047
commit 9a1abce72f
24 changed files with 566 additions and 79 deletions

View File

@ -0,0 +1,75 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.jclouds.predicates;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import org.joda.time.DateTime;
import com.google.common.base.Predicate;
/**
*
* Retries a condition until it is met or a timeout occurs.
*
* @author Adrian Cole
*/
public class RetryablePredicate<T> implements Predicate<T> {
private final int maxWait;
private final int checkInterval;
private final Predicate<T> predicate;
@Resource
protected Logger logger = Logger.NULL;
public RetryablePredicate(Predicate<T> predicate, long maxWait, long checkInterval, TimeUnit unit) {
this.predicate = predicate;
this.maxWait = (int) unit.toMillis(maxWait);
this.checkInterval = (int) unit.toMillis(checkInterval);
}
@Override
public boolean apply(T input) {
try {
for (DateTime end = new DateTime().plusMillis(maxWait); before(end); Thread
.sleep(checkInterval)) {
if (predicate.apply(input)) {
return true;
} else if (!before(end)){
return false;
}
}
} catch (InterruptedException e) {
logger.warn(e, "predicate %s on %s interrupted, returning false", input, predicate);
}
return false;
}
boolean before(DateTime end){
return new DateTime().compareTo(end) < 1;
}
}

View File

@ -0,0 +1,79 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.jclouds.predicates;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
/**
*
* Tests to see if a socket is open.
*
* @author Adrian Cole
*/
@Singleton
public class SocketOpen implements Predicate<InetSocketAddress> {
@Resource
protected Logger logger = Logger.NULL;
@Inject(optional = true)
@Named("org.jclouds.socket_timeout")
private int timeout = 2000;
@Override
public boolean apply(InetSocketAddress socketAddress) {
Socket socket = null;
try {
logger.trace("testing socket %s", socketAddress);
socket = new Socket();
socket.setReuseAddress(false);
socket.setSoLinger(false, 1);
socket.setSoTimeout(timeout);
socket.connect(socketAddress, timeout);
} catch (IOException e) {
return false;
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException ioe) {
// no work to do
}
}
}
return true;
}
}

View File

@ -0,0 +1,68 @@
package org.jclouds.predicates;
import java.util.concurrent.TimeUnit;
import org.joda.time.DateTime;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
/**
*
* @author Adrian Cole
*
*/
@Test(groups = "unit", sequential = true, testName = "jclouds.RetryablePredicateTest")
public class RetryablePredicateTest {
@Test
void testAlwaysTrue() {
RetryablePredicate<String> predicate = new RetryablePredicate<String>(Predicates
.<String> alwaysTrue(), 3, 1, TimeUnit.SECONDS);
DateTime start = new DateTime();
predicate.apply("");
DateTime now = new DateTime();
assert now.compareTo(start.plusSeconds(1)) < 0 : String.format("%s should be less than %s",
now, start.plusSeconds(1)); }
@Test
void testAlwaysFalseMillis() {
RetryablePredicate<String> predicate = new RetryablePredicate<String>(Predicates
.<String> alwaysFalse(), 3, 1, TimeUnit.SECONDS);
DateTime start = new DateTime();
predicate.apply("");
DateTime now = new DateTime();
assert now.compareTo(start.plusSeconds(3)) > 0 : String.format("%s should be less than %s",
start.plusSeconds(3), now);
assert now.compareTo(start.plusSeconds(6)) <= 0 : String.format(
"%s should be greater than %s", start.plusSeconds(6), now);
}
private static class SecondTimeTrue implements Predicate<String> {
private int count = 0;
@Override
public boolean apply(String input) {
return count++ == 1;
}
}
@Test
void testSecondTimeTrue() {
RetryablePredicate<String> predicate = new RetryablePredicate<String>(new SecondTimeTrue(),
3, 1, TimeUnit.SECONDS);
DateTime start = new DateTime();
predicate.apply("");
DateTime now = new DateTime();
assert now.compareTo(start.plusSeconds(1)) > 0 : String.format("%s should be greater than %s",
now,start.plusSeconds(1));
assert now.compareTo(start.plusSeconds(2)) <= 0 : String.format(
"%s should be greater than %s", start.plusSeconds(2), now);
}
}

View File

@ -26,6 +26,7 @@ package org.jclouds.vcloud;
import static org.jclouds.vcloud.VCloudMediaType.CATALOG_XML; import static org.jclouds.vcloud.VCloudMediaType.CATALOG_XML;
import static org.jclouds.vcloud.VCloudMediaType.TASKSLIST_XML; import static org.jclouds.vcloud.VCloudMediaType.TASKSLIST_XML;
import static org.jclouds.vcloud.VCloudMediaType.TASK_XML; import static org.jclouds.vcloud.VCloudMediaType.TASK_XML;
import static org.jclouds.vcloud.VCloudMediaType.VAPP_XML;
import static org.jclouds.vcloud.VCloudMediaType.VDC_XML; import static org.jclouds.vcloud.VCloudMediaType.VDC_XML;
import java.net.URI; import java.net.URI;
@ -157,4 +158,9 @@ public interface VCloudClient {
@Path("/action/cancel") @Path("/action/cancel")
Future<Void> cancelTask(@Endpoint URI task); Future<Void> cancelTask(@Endpoint URI task);
@GET
@Consumes(VAPP_XML)
@Endpoint(org.jclouds.vcloud.endpoints.VCloud.class)
@Path("/vapp/{vAppId}")
String getVApp(@PathParam("vAppId") String appId);
} }

View File

@ -23,6 +23,8 @@
*/ */
package org.jclouds.vcloud; package org.jclouds.vcloud;
import java.util.concurrent.Future;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
@ -52,5 +54,5 @@ public interface VCloudDiscovery {
@Endpoint(Org.class) @Endpoint(Org.class)
@Consumes(VCloudMediaType.ORG_XML) @Consumes(VCloudMediaType.ORG_XML)
@XMLResponseParser(OrgHandler.class) @XMLResponseParser(OrgHandler.class)
Organization getOrganization(); Future<? extends Organization> getOrganization();
} }

View File

@ -24,6 +24,7 @@
package org.jclouds.vcloud; package org.jclouds.vcloud;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Future;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.POST; import javax.ws.rs.POST;
@ -66,5 +67,5 @@ public interface VCloudLogin {
@ResponseParser(ParseLoginResponseFromHeaders.class) @ResponseParser(ParseLoginResponseFromHeaders.class)
@Path("/login") @Path("/login")
@Consumes(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATION_XML)
VCloudSession login(); Future<VCloudSession> login();
} }

View File

@ -39,6 +39,7 @@ import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.RestClientFactory; import org.jclouds.rest.RestClientFactory;
import org.jclouds.util.Utils;
import org.jclouds.vcloud.VCloudDiscovery; import org.jclouds.vcloud.VCloudDiscovery;
import org.jclouds.vcloud.VCloudLogin; import org.jclouds.vcloud.VCloudLogin;
import org.jclouds.vcloud.VCloudToken; import org.jclouds.vcloud.VCloudToken;
@ -85,7 +86,12 @@ public class VCloudDiscoveryRestClientModule extends AbstractModule {
@Named(PROPERTY_VCLOUD_SESSIONINTERVAL) long seconds, final VCloudLogin login) { @Named(PROPERTY_VCLOUD_SESSIONINTERVAL) long seconds, final VCloudLogin login) {
return new ExpirableSupplier<VCloudSession>(new Supplier<VCloudSession>() { return new ExpirableSupplier<VCloudSession>(new Supplier<VCloudSession>() {
public VCloudSession get() { public VCloudSession get() {
return login.login(); try {
return login.login().get(45, TimeUnit.SECONDS);
} catch (Exception e) {
Utils.<RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new RuntimeException("Error logging in", e);
}
} }
}, seconds, TimeUnit.SECONDS); }, seconds, TimeUnit.SECONDS);
} }

View File

@ -68,29 +68,30 @@ public class VCloudRestClientModule extends AbstractModule {
@Provides @Provides
@Catalog @Catalog
@Singleton @Singleton
protected URI provideCatalog(VCloudDiscovery discovery) { protected URI provideCatalog(VCloudDiscovery discovery) throws InterruptedException, ExecutionException, TimeoutException {
return discovery.getOrganization().getCatalog().getLocation(); return discovery.getOrganization().get(45, TimeUnit.SECONDS).getCatalog().getLocation();
} }
@Provides @Provides
@CatalogItemRoot @CatalogItemRoot
@Singleton @Singleton
String provideCatalogItemRoot(@VCloud URI vcloudUri) { String provideCatalogItemRoot(@VCloud URI vcloudUri) {
return vcloudUri.toASCIIString()+"/catalogItem"; return vcloudUri.toASCIIString() + "/catalogItem";
} }
@Provides @Provides
@VAppRoot @VAppRoot
@Singleton @Singleton
String provideVAppRoot(@VCloud URI vcloudUri) { String provideVAppRoot(@VCloud URI vcloudUri) {
return vcloudUri.toASCIIString()+"/vapp"; return vcloudUri.toASCIIString() + "/vapp";
} }
@Provides @Provides
@VDC @VDC
@Singleton @Singleton
protected URI provideDefaultVDC(VCloudDiscovery discovery) { protected URI provideDefaultVDC(VCloudDiscovery discovery) throws InterruptedException, ExecutionException, TimeoutException {
return discovery.getOrganization().getVDCs().values().iterator().next().getLocation(); return discovery.getOrganization().get(45, TimeUnit.SECONDS).getVDCs().values().iterator()
.next().getLocation();
} }
@Provides @Provides
@ -105,7 +106,7 @@ public class VCloudRestClientModule extends AbstractModule {
@Provides @Provides
@TasksList @TasksList
@Singleton @Singleton
protected URI provideDefaultTasksList(VCloudDiscovery discovery) { protected URI provideDefaultTasksList(VCloudDiscovery discovery) throws InterruptedException, ExecutionException, TimeoutException {
return discovery.getOrganization().getTasksLists().values().iterator().next().getLocation(); return discovery.getOrganization().get(45, TimeUnit.SECONDS).getTasksLists().values().iterator().next().getLocation();
} }
} }

View File

@ -18,12 +18,11 @@ public class CatalogIdToUri implements Function<Object, String> {
@Inject @Inject
@CatalogItemRoot @CatalogItemRoot
private String catalogItemRoot; private String catalogItemRoot;
@Override
public String apply(Object from) { public String apply(Object from) {
checkArgument(checkNotNull(from, "from") instanceof Integer, checkArgument(checkNotNull(from, "from") instanceof Integer,
"this binder is only valid for Integers!"); "this binder is only valid for Integers!");
return String.format("%s/%d",catalogItemRoot,from); return String.format("%s/%d", catalogItemRoot, from);
} }
} }

View File

@ -18,12 +18,11 @@ public class VAppIdToUri implements Function<Object, String> {
@Inject @Inject
@VAppRoot @VAppRoot
private String vAppRoot; private String vAppRoot;
@Override
public String apply(Object from) { public String apply(Object from) {
checkArgument(checkNotNull(from, "from") instanceof Integer, checkArgument(checkNotNull(from, "from") instanceof Integer,
"this binder is only valid for Integers!"); "this binder is only valid for Integers!");
return String.format("%s/%d",vAppRoot,from); return String.format("%s/%d", vAppRoot, from);
} }
} }

View File

@ -89,6 +89,13 @@ public class VCloudClientLiveTest {
} }
} }
@Test(enabled = false)
public void testGetVApp() throws Exception {
String response = connection.getVApp("188849-2");
assertNotNull(response);
System.out.println(response);
}
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
String endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"), String endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"),

View File

@ -33,6 +33,7 @@ import static org.testng.Assert.assertNotNull;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -89,7 +90,7 @@ public class VCloudDiscoveryLiveTest {
@Test @Test
public void testOrganization() throws Exception { public void testOrganization() throws Exception {
Organization response = context.getApi().getOrganization(); Organization response = context.getApi().getOrganization().get(45, TimeUnit.SECONDS);
assertNotNull(response); assertNotNull(response);
assertNotNull(account); assertNotNull(account);
assertNotNull(response.getCatalog()); assertNotNull(response.getCatalog());

View File

@ -32,6 +32,7 @@ import static org.testng.Assert.assertNotNull;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -91,7 +92,7 @@ public class VCloudLoginLiveTest {
public void testLogin() throws Exception { public void testLogin() throws Exception {
VCloudLogin authentication = context.getApi(); VCloudLogin authentication = context.getApi();
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
VCloudSession response = authentication.login(); VCloudSession response = authentication.login().get(45, TimeUnit.SECONDS);
assertNotNull(response); assertNotNull(response);
assertNotNull(response.getVCloudToken()); assertNotNull(response.getVCloudToken());
assertNotNull(response.getOrgs()); assertNotNull(response.getOrgs());

View File

@ -30,6 +30,10 @@ import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_USER;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
@ -70,6 +74,25 @@ public class VCloudDiscoveryRestClientModuleTest {
}); });
} }
public static abstract class FutureBase<V> implements Future<V> {
public boolean cancel(boolean b) {
return false;
}
public boolean isCancelled() {
return false;
}
public boolean isDone() {
return true;
}
public V get(long l, TimeUnit timeUnit) throws InterruptedException, ExecutionException,
TimeoutException {
return get();
}
}
@Test @Test
void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException { void testUpdatesOnlyOncePerSecond() throws NoSuchMethodException, InterruptedException {
VCloudDiscoveryRestClientModule module = new VCloudDiscoveryRestClientModule(); VCloudDiscoveryRestClientModule module = new VCloudDiscoveryRestClientModule();
@ -77,18 +100,24 @@ public class VCloudDiscoveryRestClientModuleTest {
private final AtomicInteger token = new AtomicInteger(); private final AtomicInteger token = new AtomicInteger();
public VCloudSession login() { public Future<VCloudSession> login() {
return new VCloudSession() { return new FutureBase<VCloudSession>() {
@Override
public VCloudSession get() throws InterruptedException, ExecutionException {
return new VCloudSession() {
public Map<String, NamedLink> getOrgs() { public Map<String, NamedLink> getOrgs() {
return null; return null;
}
public String getVCloudToken() {
return token.incrementAndGet() + "";
}
};
} }
public String getVCloudToken() {
return token.incrementAndGet() + "";
}
}; };
} }
}; };

View File

@ -0,0 +1,63 @@
package org.jclouds.vcloud.predicates;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.TaskStatus;
import com.google.common.base.Predicate;
/**
*
* Tests to see if a task succeeds.
*
* @author Adrian Cole
*/
@Singleton
public class TaskSuccess implements Predicate<URI> {
private final VCloudClient client;
@Inject(optional = true)
@Named("org.jclouds.vcloud.timeout")
private long taskTimeout = 30000;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public TaskSuccess(VCloudClient client) {
this.client = client;
}
public boolean apply(URI taskUri) {
logger.trace("looking for status on task %s", taskUri);
Task task;
try {
task = client.getTask(taskUri).get(taskTimeout, TimeUnit.MILLISECONDS);
logger.trace("%s: looking for status %s: currently: %s", task, TaskStatus.SUCCESS, task
.getStatus());
return task.getStatus() == TaskStatus.SUCCESS;
} catch (InterruptedException e) {
logger.warn(e, "%s interrupted, returning false", taskUri);
} catch (ExecutionException e) {
logger.warn(e, "%s exception, returning false", taskUri);
} catch (TimeoutException e) {
logger.warn(e, "%s timeout, returning false", taskUri);
}
return false;
}
}

View File

@ -98,12 +98,25 @@
<priority value="DEBUG" /> <priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" /> <appender-ref ref="ASYNCWIRE" />
</category> </category>
<category name="org.jclouds.predicates.SocketOpen">
<priority value="TRACE" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="org.jclouds.vcloud.predicates.TaskSuccess">
<priority value="TRACE" />
<appender-ref ref="ASYNCWIRE" />
</category>
<!--
<category name="jclouds.http.wire"> <category name="jclouds.http.wire">
<priority value="DEBUG" /> <priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" /> <appender-ref ref="ASYNCWIRE" />
</category> </category>
<!-- ======================= --> --><!-- ======================= -->
<!-- Setup the Root category --> <!-- Setup the Root category -->
<!-- ======================= --> <!-- ======================= -->

View File

@ -29,6 +29,10 @@ public class BindInstantiateVAppTemplateParamsToXmlEntity implements MapBinder {
public void bindToRequest(HttpRequest request, Map<String, String> postParams) { public void bindToRequest(HttpRequest request, Map<String, String> postParams) {
String name = checkNotNull(postParams.get("name"), "name parameter not present"); String name = checkNotNull(postParams.get("name"), "name parameter not present");
String password = checkNotNull(postParams.get("password"), "password parameter not present");
String row = checkNotNull(postParams.get("row"), "row parameter not present");
String group = checkNotNull(postParams.get("group"), "group parameter not present");
String template = checkNotNull(postParams.get("template"), "template parameter not present"); String template = checkNotNull(postParams.get("template"), "template parameter not present");
String count = checkNotNull(postParams.get("count"), "count parameter not present"); String count = checkNotNull(postParams.get("count"), "count parameter not present");
String megabytes = checkNotNull(postParams.get("megabytes"), String megabytes = checkNotNull(postParams.get("megabytes"),
@ -36,6 +40,9 @@ public class BindInstantiateVAppTemplateParamsToXmlEntity implements MapBinder {
String network = checkNotNull(postParams.get("network"), "network parameter not present"); String network = checkNotNull(postParams.get("network"), "network parameter not present");
String entity = xmlTemplate.replaceAll("\\{name\\}", name); String entity = xmlTemplate.replaceAll("\\{name\\}", name);
entity = entity.replaceAll("\\{password\\}", password);
entity = entity.replaceAll("\\{row\\}", row);
entity = entity.replaceAll("\\{group\\}", group);
entity = entity.replaceAll("\\{template\\}", template); entity = entity.replaceAll("\\{template\\}", template);
entity = entity.replaceAll("\\{count\\}", count); entity = entity.replaceAll("\\{count\\}", count);
entity = entity.replaceAll("\\{megabytes\\}", megabytes); entity = entity.replaceAll("\\{megabytes\\}", megabytes);

View File

@ -24,6 +24,13 @@ public class InstantiateVAppTemplateOptions extends BindInstantiateVAppTemplateP
@Network @Network
private URI defaultNetwork; private URI defaultNetwork;
@VisibleForTesting
String password = "password";
@VisibleForTesting
String group = "default";
@VisibleForTesting
String row = "default";
@VisibleForTesting @VisibleForTesting
String cpuCount = "1"; String cpuCount = "1";
@VisibleForTesting @VisibleForTesting
@ -35,6 +42,9 @@ public class InstantiateVAppTemplateOptions extends BindInstantiateVAppTemplateP
Map<String, String> copy = Maps.newHashMap(); Map<String, String> copy = Maps.newHashMap();
copy.putAll(postParams); copy.putAll(postParams);
copy.put("count", cpuCount); copy.put("count", cpuCount);
copy.put("password", password);
copy.put("group", group);
copy.put("row", row);
copy.put("megabytes", megabytes); copy.put("megabytes", megabytes);
copy.put("network", network != null ? network : defaultNetwork.toASCIIString()); copy.put("network", network != null ? network : defaultNetwork.toASCIIString());
super.bindToRequest(request, copy); super.bindToRequest(request, copy);
@ -57,6 +67,21 @@ public class InstantiateVAppTemplateOptions extends BindInstantiateVAppTemplateP
return this; return this;
} }
public InstantiateVAppTemplateOptions withPassword(String password) {
this.password = password;
return this;
}
public InstantiateVAppTemplateOptions inGroup(String group) {
this.group = group;
return this;
}
public InstantiateVAppTemplateOptions inRow(String row) {
this.row = row;
return this;
}
public static class Builder { public static class Builder {
/** /**
@ -82,5 +107,30 @@ public class InstantiateVAppTemplateOptions extends BindInstantiateVAppTemplateP
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions(); InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.inNetwork(networkLocation); return options.inNetwork(networkLocation);
} }
/**
* @see InstantiateVAppTemplateOptions#withPassword(String)
*/
public static InstantiateVAppTemplateOptions withPassword(String password) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.withPassword(password);
}
/**
* @see InstantiateVAppTemplateOptions#inGroup(String)
*/
public static InstantiateVAppTemplateOptions inGroup(String group) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.inGroup(group);
}
/**
* @see InstantiateVAppTemplateOptions#inRow(String)
*/
public static InstantiateVAppTemplateOptions inRow(String row) {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
return options.inRow(row);
}
} }
} }

View File

@ -0,0 +1,4 @@
<InternetService xmlns="urn:tmrk:vCloudExpress-1.0"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Id>{id}</Id>{options}
</InternetService>

View File

@ -5,11 +5,11 @@
<ProductSection xmlns:q1="http://www.vmware.com/vcloud/v1" <ProductSection xmlns:q1="http://www.vmware.com/vcloud/v1"
xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"> xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1">
<Property xmlns="http://schemas.dmtf.org/ovf/envelope/1" <Property xmlns="http://schemas.dmtf.org/ovf/envelope/1"
ovf:key="password" ovf:value="secretPassword" /> ovf:key="password" ovf:value="{password}" />
<Property xmlns="http://schemas.dmtf.org/ovf/envelope/1" <Property xmlns="http://schemas.dmtf.org/ovf/envelope/1"
ovf:key="row" ovf:value="Row1" /> ovf:key="row" ovf:value="{row}" />
<Property xmlns="http://schemas.dmtf.org/ovf/envelope/1" <Property xmlns="http://schemas.dmtf.org/ovf/envelope/1"
ovf:key="group" ovf:value="Group1" /> ovf:key="group" ovf:value="{group}" />
</ProductSection> </ProductSection>
<VirtualHardwareSection xmlns:q1="http://www.vmware.com/vcloud/v1"> <VirtualHardwareSection xmlns:q1="http://www.vmware.com/vcloud/v1">
<Item xmlns="http://schemas.dmtf.org/ovf/envelope/1"> <Item xmlns="http://schemas.dmtf.org/ovf/envelope/1">

View File

@ -36,10 +36,10 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshClient.Factory; import org.jclouds.ssh.SshClient.Factory;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
@ -48,6 +48,7 @@ import org.jclouds.vcloud.VCloudClientLiveTest;
import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.TaskStatus; import org.jclouds.vcloud.domain.TaskStatus;
import org.jclouds.vcloud.domain.VAppStatus; import org.jclouds.vcloud.domain.VAppStatus;
import org.jclouds.vcloud.predicates.TaskSuccess;
import org.jclouds.vcloud.terremark.domain.InternetService; import org.jclouds.vcloud.terremark.domain.InternetService;
import org.jclouds.vcloud.terremark.domain.Node; import org.jclouds.vcloud.terremark.domain.Node;
import org.jclouds.vcloud.terremark.domain.ResourceType; import org.jclouds.vcloud.terremark.domain.ResourceType;
@ -58,7 +59,6 @@ import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
/** /**
@ -77,6 +77,10 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
private Node node; private Node node;
private VApp vApp; private VApp vApp;
private RetryablePredicate<InetSocketAddress> socketTester;
private RetryablePredicate<URI> successTester;
public static final String PREFIX = System.getProperty("user.name") + "-terremark"; public static final String PREFIX = System.getProperty("user.name") + "-terremark";
@Test @Test
@ -95,12 +99,16 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
String serverName = "adriantest"; String serverName = "adriantest";
int processorCount = 1; int processorCount = 1;
int memory = 512; int memory = 512;
long hardDisk = 4194304; // long hardDisk = 4194304;
String catalogOs = "Ubuntu JeOS 9.04 (32-bit)"; // String catalogOs = "Ubuntu JeOS 9.04 (32-bit)";
String expectedOs = "Ubuntu Linux (32-bit)"; // String expectedOs = "Ubuntu Linux (32-bit)";
long hardDisk = 4194304 / 4 * 10;
String catalogOs = "CentOS 5.3 (32-bit)";
String expectedOs = "Red Hat Enterprise Linux 5 (32-bit)";
int templateId = tmClient.getCatalog().get(45, TimeUnit.SECONDS).get(catalogOs).getId(); int templateId = tmClient.getCatalog().get(45, TimeUnit.SECONDS).get(catalogOs).getId();
System.out.printf("%d: instantiating vApp%n", System.currentTimeMillis());
vApp = tmClient.instantiateVAppTemplate(serverName, templateId).get(45, TimeUnit.SECONDS); vApp = tmClient.instantiateVAppTemplate(serverName, templateId).get(45, TimeUnit.SECONDS);
assertEquals(vApp.getStatus(), VAppStatus.CREATING); assertEquals(vApp.getStatus(), VAppStatus.CREATING);
@ -127,13 +135,17 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 501); assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 501);
} }
deployTask = blockUntilSuccess(deployTask); assert successTester.apply(deployTask.getLocation());
System.out.printf("%d: done deploying vApp%n", System.currentTimeMillis());
vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS); vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS);
verifyConfigurationOfVApp(vApp, serverName, expectedOs, processorCount, memory, hardDisk); verifyConfigurationOfVApp(vApp, serverName, expectedOs, processorCount, memory, hardDisk);
assertEquals(vApp.getStatus(), VAppStatus.OFF); assertEquals(vApp.getStatus(), VAppStatus.OFF);
deployTask = blockUntilSuccess(tmClient.powerOnVApp(vApp.getId()).get(45, TimeUnit.SECONDS)); assert successTester.apply(tmClient.powerOnVApp(vApp.getId()).get(45, TimeUnit.SECONDS)
.getLocation());
System.out.printf("%d: done powering on vApp%n", System.currentTimeMillis());
vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS); vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS);
assertEquals(vApp.getStatus(), VAppStatus.ON); assertEquals(vApp.getStatus(), VAppStatus.ON);
@ -151,13 +163,7 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
node = tmClient.addNode(is.getId(), vApp.getNetworkToAddresses().values().iterator().next(), node = tmClient.addNode(is.getId(), vApp.getNetworkToAddresses().values().iterator().next(),
vApp.getName() + "-SSH", 22).get(45, TimeUnit.SECONDS); vApp.getName() + "-SSH", 22).get(45, TimeUnit.SECONDS);
publicIp = is.getPublicIpAddress().getAddress(); publicIp = is.getPublicIpAddress().getAddress();
try { doCheckPass(publicIp);
doCheckPass(publicIp);
} catch (Exception e) {
// TODO - harden this up, when we stop hanging
System.err.printf("%s:22 -> %s:22%n%s%n", vApp.getNetworkToAddresses().values().iterator()
.next(), publicIp, e.getMessage());
}
} }
@Test(dependsOnMethods = "testPublicIp") @Test(dependsOnMethods = "testPublicIp")
@ -178,15 +184,20 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 501); assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 501);
} }
blockUntilSuccess(tmClient.resetVApp(vApp.getId()).get(45, TimeUnit.SECONDS)); assert successTester.apply(tmClient.resetVApp(vApp.getId()).get(45, TimeUnit.SECONDS)
.getLocation());
vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS); vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS);
assertEquals(vApp.getStatus(), VAppStatus.ON); assertEquals(vApp.getStatus(), VAppStatus.ON);
tmClient.shutdownVApp(vApp.getId()).get(45, TimeUnit.SECONDS); // TODO we need to determine whether shutdown is supported before invoking it.
vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS); // tmClient.shutdownVApp(vApp.getId()).get(45, TimeUnit.SECONDS);
assertEquals(vApp.getStatus(), VAppStatus.ON); // vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS);
// assertEquals(vApp.getStatus(), VAppStatus.ON);
assert successTester.apply(tmClient.powerOffVApp(vApp.getId()).get(45, TimeUnit.SECONDS)
.getLocation());
blockUntilSuccess(tmClient.powerOffVApp(vApp.getId()).get(45, TimeUnit.SECONDS));
vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS); vApp = tmClient.getVApp(vApp.getId()).get(45, TimeUnit.SECONDS);
assertEquals(vApp.getStatus(), VAppStatus.OFF); assertEquals(vApp.getStatus(), VAppStatus.OFF);
} }
@ -208,18 +219,6 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
.get(ResourceType.VIRTUAL_DISK).getVirtualQuantity()); .get(ResourceType.VIRTUAL_DISK).getVirtualQuantity());
} }
private Task blockUntilSuccess(Task task) throws InterruptedException, ExecutionException,
TimeoutException {
for (task = tmClient.getTask(task.getLocation()).get(30, TimeUnit.SECONDS); task.getStatus() != TaskStatus.SUCCESS; task = tmClient
.getTask(task.getLocation()).get(30, TimeUnit.SECONDS)) {
System.out.printf("%s blocking on status active: currently: %s%n", task.getOwner()
.getName(), task.getStatus());
Thread.sleep(5 * 1000);
}
System.out.printf("%s complete%n", task.getResult().getName());
return task;
}
private Task getLastTaskFor(URI owner) throws InterruptedException, ExecutionException, private Task getLastTaskFor(URI owner) throws InterruptedException, ExecutionException,
TimeoutException { TimeoutException {
return Iterables.getLast(tmClient.getDefaultTasksList().get(45, TimeUnit.SECONDS) return Iterables.getLast(tmClient.getDefaultTasksList().get(45, TimeUnit.SECONDS)
@ -227,11 +226,17 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
} }
private void doCheckPass(InetAddress address) throws IOException { private void doCheckPass(InetAddress address) throws IOException {
System.out.printf("%s:%s%n", address, 22); InetSocketAddress socket = new InetSocketAddress(address, 22);
SshClient connection = sshFactory.create(new InetSocketAddress(address, 22), "vcloud",
"p4ssw0rd"); System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(),
socket);
assert socketTester.apply(socket);
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), socket);
SshClient connection = sshFactory.create(socket, "vcloud", "p4ssw0rd");
try { try {
connection.connect(); connection.connect();
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), socket);
InputStream etcPasswd = connection.get("/etc/passwd"); InputStream etcPasswd = connection.get("/etc/passwd");
Utils.toStringAndClose(etcPasswd); Utils.toStringAndClose(etcPasswd);
} finally { } finally {
@ -248,8 +253,10 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
tmClient.deleteInternetService(is.getId()).get(30, TimeUnit.SECONDS); tmClient.deleteInternetService(is.getId()).get(30, TimeUnit.SECONDS);
if (vApp != null) { if (vApp != null) {
try { try {
blockUntilSuccess(tmClient.powerOffVApp(vApp.getId()).get(45, TimeUnit.SECONDS)); successTester.apply(tmClient.powerOffVApp(vApp.getId()).get(45, TimeUnit.SECONDS)
.getLocation());
} catch (Exception e) { } catch (Exception e) {
} }
tmClient.deleteVApp(vApp.getId()).get(45, TimeUnit.SECONDS); tmClient.deleteVApp(vApp.getId()).get(45, TimeUnit.SECONDS);
} }
@ -260,13 +267,19 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
public void setupClient() { public void setupClient() {
account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user"); account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key"); String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
connection = tmClient = new TerremarkVCloudContextBuilder( Injector injector = new TerremarkVCloudContextBuilder(new TerremarkVCloudPropertiesBuilder(
new TerremarkVCloudPropertiesBuilder(account, key).build()).withModules( account, key).build()).withModules(new Log4JLoggingModule(),
new Log4JLoggingModule()).buildContext().getApi(); new JschSshClientModule()).buildInjector();
Injector injector = Guice.createInjector(new Log4JLoggingModule(), new JschSshClientModule(),
new ExecutorServiceModule(new WithinThreadExecutorService()));
sshFactory = injector.getInstance(SshClient.Factory.class);
connection = tmClient = injector.getInstance(TerremarkVCloudClient.class);
sshFactory = injector.getInstance(SshClient.Factory.class);
socketTester = new RetryablePredicate<InetSocketAddress>(injector
.getInstance(SocketOpen.class), 130, 10, TimeUnit.SECONDS);// make it longer then
// default internet
// service timeout
successTester = new RetryablePredicate<URI>(injector.getInstance(TaskSuccess.class), 300, 10,
TimeUnit.SECONDS);
} }
} }

View File

@ -78,13 +78,16 @@ public class BindInstantiateVAppTemplateParamsToXmlEntityTest {
Map<String, String> map = Maps.newHashMap(); Map<String, String> map = Maps.newHashMap();
map.put("name", "name"); map.put("name", "name");
map.put("password", "password");
map.put("row", "row");
map.put("group", "group");
map.put("template", "http://catalogItem/3"); map.put("template", "http://catalogItem/3");
map.put("count", "1"); map.put("count", "1");
map.put("megabytes", "512"); map.put("megabytes", "512");
map.put("network", "http://network"); map.put("network", "http://network");
binder.bindToRequest(request, map); binder.bindToRequest(request, map);
assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), "application/unknown"); assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), "application/unknown");
assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), "2247"); assertEquals(request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH), "2239");
assertEquals(request.getEntity(), expected); assertEquals(request.getEntity(), expected);
} }

View File

@ -1,8 +1,11 @@
package org.jclouds.vcloud.terremark.options; package org.jclouds.vcloud.terremark.options;
import static org.jclouds.vcloud.terremark.options.InstantiateVAppTemplateOptions.Builder.cpuCount; import static org.jclouds.vcloud.terremark.options.InstantiateVAppTemplateOptions.Builder.cpuCount;
import static org.jclouds.vcloud.terremark.options.InstantiateVAppTemplateOptions.Builder.inGroup;
import static org.jclouds.vcloud.terremark.options.InstantiateVAppTemplateOptions.Builder.inNetwork; import static org.jclouds.vcloud.terremark.options.InstantiateVAppTemplateOptions.Builder.inNetwork;
import static org.jclouds.vcloud.terremark.options.InstantiateVAppTemplateOptions.Builder.inRow;
import static org.jclouds.vcloud.terremark.options.InstantiateVAppTemplateOptions.Builder.megabytes; import static org.jclouds.vcloud.terremark.options.InstantiateVAppTemplateOptions.Builder.megabytes;
import static org.jclouds.vcloud.terremark.options.InstantiateVAppTemplateOptions.Builder.withPassword;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;
@ -23,6 +26,63 @@ public class InstantiateVAppTemplateOptionsTest {
Injector injector = Guice.createInjector(new ParserModule()); Injector injector = Guice.createInjector(new ParserModule());
@Test
public void testInGroupDefault() {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
assertEquals(options.group, "default");
}
@Test
public void testInGroup() {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
options.inGroup("group1");
assertEquals(options.group, "group1");
}
@Test
public void testInGroupStatic() {
InstantiateVAppTemplateOptions options = inGroup("group1");
assertEquals(options.group, "group1");
}
@Test
public void testInRowDefault() {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
assertEquals(options.row, "default");
}
@Test
public void testInRow() {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
options.inRow("row1");
assertEquals(options.row, "row1");
}
@Test
public void testInRowStatic() {
InstantiateVAppTemplateOptions options = inRow("row1");
assertEquals(options.row, "row1");
}
@Test
public void testWithPasswordDefault() {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
assertEquals(options.password, "password");
}
@Test
public void testWithPassword() {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
options.withPassword("password1");
assertEquals(options.password, "password1");
}
@Test
public void testWithPasswordStatic() {
InstantiateVAppTemplateOptions options = withPassword("password1");
assertEquals(options.password, "password1");
}
@Test @Test
public void testInNetwork() { public void testInNetwork() {
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions(); InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();

View File

@ -5,11 +5,11 @@
<ProductSection xmlns:q1="http://www.vmware.com/vcloud/v1" <ProductSection xmlns:q1="http://www.vmware.com/vcloud/v1"
xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"> xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1">
<Property xmlns="http://schemas.dmtf.org/ovf/envelope/1" <Property xmlns="http://schemas.dmtf.org/ovf/envelope/1"
ovf:key="password" ovf:value="secretPassword" /> ovf:key="password" ovf:value="password" />
<Property xmlns="http://schemas.dmtf.org/ovf/envelope/1" <Property xmlns="http://schemas.dmtf.org/ovf/envelope/1"
ovf:key="row" ovf:value="Row1" /> ovf:key="row" ovf:value="row" />
<Property xmlns="http://schemas.dmtf.org/ovf/envelope/1" <Property xmlns="http://schemas.dmtf.org/ovf/envelope/1"
ovf:key="group" ovf:value="Group1" /> ovf:key="group" ovf:value="group" />
</ProductSection> </ProductSection>
<VirtualHardwareSection xmlns:q1="http://www.vmware.com/vcloud/v1"> <VirtualHardwareSection xmlns:q1="http://www.vmware.com/vcloud/v1">
<Item xmlns="http://schemas.dmtf.org/ovf/envelope/1"> <Item xmlns="http://schemas.dmtf.org/ovf/envelope/1">