stabilized bluelock

This commit is contained in:
Adrian Cole 2011-06-01 20:30:30 -07:00
parent ccb9709d05
commit 86129df416
8 changed files with 71 additions and 58 deletions

View File

@ -67,50 +67,47 @@ public class VCloudDestroyNodeStrategy implements DestroyNodeStrategy {
VApp vApp = client.getVAppClient().getVApp(vappId); VApp vApp = client.getVAppClient().getVApp(vappId);
if (vApp == null) if (vApp == null)
return null; return null;
vApp = powerOffVAppIfDeployed(vApp);
waitForPendingTasksToComplete(vApp);
vApp = undeployVAppIfDeployed(vApp); vApp = undeployVAppIfDeployed(vApp);
deleteVApp(vappId); deleteVApp(vApp);
try { try {
return getNode.getNode(id); return getNode.getNode(id);
} catch (AuthorizationException e) { } catch (AuthorizationException e) {
// vcloud bug will sometimes throw an exception getting the vapp right after deleting it.
logger.trace("authorization error getting %s after deletion: %s", id, e.getMessage()); logger.trace("authorization error getting %s after deletion: %s", id, e.getMessage());
return null; return null;
} }
} }
void deleteVApp(URI vappId) { void waitForPendingTasksToComplete(VApp vApp) {
logger.debug(">> deleting vApp(%s)", vappId); for (Task task : vApp.getTasks())
Task task = client.getVAppClient().deleteVApp(vappId); waitForTask(task, vApp);
if (!successTester.apply(task.getHref())) {
throw new RuntimeException(String.format("failed to %s %s: %s", "delete", vappId, task));
} }
logger.debug("<< deleted vApp(%s)", vappId);
public void waitForTask(Task task, VApp vAppResponse) {
if (!successTester.apply(task.getHref())) {
throw new RuntimeException(String.format("failed to %s %s: %s", task.getName(), vAppResponse.getName(), task));
}
}
void deleteVApp(VApp vApp) {
logger.debug(">> deleting vApp(%s)", vApp.getHref());
waitForTask(client.getVAppClient().deleteVApp(vApp.getHref()), vApp);
logger.debug("<< deleted vApp(%s)", vApp.getHref());
} }
VApp undeployVAppIfDeployed(VApp vApp) { VApp undeployVAppIfDeployed(VApp vApp) {
if (vApp.getStatus().compareTo(Status.RESOLVED) > 0) { if (vApp.getStatus() != Status.OFF) {
logger.debug(">> undeploying vApp(%s), current status: %s", vApp.getName(), vApp.getStatus()); logger.debug(">> undeploying vApp(%s), current status: %s", vApp.getName(), vApp.getStatus());
Task task = client.getVAppClient().undeployVApp(vApp.getHref()); try {
if (!successTester.apply(task.getHref())) { waitForTask(client.getVAppClient().undeployVApp(vApp.getHref()), vApp);
// TODO timeout
throw new RuntimeException(String.format("failed to %s %s: %s", "undeploy", vApp.getName(), task));
}
vApp = client.getVAppClient().getVApp(vApp.getHref()); vApp = client.getVAppClient().getVApp(vApp.getHref());
logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName()); logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
} catch (IllegalStateException e) {
logger.warn(e, "<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
} }
return vApp;
}
VApp powerOffVAppIfDeployed(VApp vApp) {
if (vApp.getStatus().compareTo(Status.OFF) > 0) {
logger.debug(">> powering off vApp(%s), current status: %s", vApp.getName(), vApp.getStatus());
Task task = client.getVAppClient().powerOffVApp(vApp.getHref());
if (!successTester.apply(task.getHref())) {
// TODO timeout
throw new RuntimeException(String.format("failed to %s %s: %s", "powerOff", vApp.getName(), task));
}
vApp = client.getVAppClient().getVApp(vApp.getHref());
logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
} }
return vApp; return vApp;
} }

View File

@ -34,7 +34,9 @@ import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.CatalogItem; import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.Org; import org.jclouds.vcloud.domain.Org;
import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppTemplate; import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.options.CatalogItemOptions; import org.jclouds.vcloud.options.CatalogItemOptions;
import org.jclouds.vcloud.predicates.TaskSuccess; import org.jclouds.vcloud.predicates.TaskSuccess;
@ -125,20 +127,17 @@ public class VAppTemplateClientLiveTest extends BaseVCloudClientLiveTest {
Predicate<URI> taskTester = new RetryablePredicate<URI>(new TaskSuccess(getVCloudApi()), 600, 5, Predicate<URI> taskTester = new RetryablePredicate<URI>(new TaskSuccess(getVCloudApi()), 600, 5,
TimeUnit.SECONDS); TimeUnit.SECONDS);
// I have to powerOff first
Task task = getVCloudApi().getVAppClient().powerOffVApp(URI.create(node.getId()));
// wait up to ten minutes per above
assert taskTester.apply(task.getHref()) : node;
// having a problem where the api is returning an error telling us to stop!
// I have to undeploy first // I have to undeploy first
task = getVCloudApi().getVAppClient().undeployVApp(URI.create(node.getId())); Task task = getVCloudApi().getVAppClient().undeployVApp(URI.create(node.getId()));
// wait up to ten minutes per above // wait up to ten minutes per above
assert taskTester.apply(task.getHref()) : node; assert taskTester.apply(task.getHref()) : node;
VApp vApp = getVCloudApi().getVAppClient().getVApp(URI.create(node.getId()));
// wait up to ten minutes per above
assertEquals(vApp.getStatus(), Status.OFF);
// vdc is equiv to the node's location // vdc is equiv to the node's location
// vapp uri is the same as the node's id // vapp uri is the same as the node's id
vappTemplate = getVCloudApi().getVAppTemplateClient().captureVAppAsTemplateInVDC(URI.create(node.getId()), vappTemplate = getVCloudApi().getVAppTemplateClient().captureVAppAsTemplateInVDC(URI.create(node.getId()),
@ -159,7 +158,7 @@ public class VAppTemplateClientLiveTest extends BaseVCloudClientLiveTest {
assertEquals(item.getName(), "fooname"); assertEquals(item.getName(), "fooname");
assertEquals(item.getDescription(), "description"); assertEquals(item.getDescription(), "description");
assertEquals(item.getProperties(), ImmutableMap.of("foo", "bar")); assertEquals(item.getProperties(), ImmutableMap.of("foo", "bar"));
assertEquals(item.getEntity().getName(), vappTemplate.getName()); assertEquals(item.getEntity().getName(), "fooname");
assertEquals(item.getEntity().getHref(), vappTemplate.getHref()); assertEquals(item.getEntity().getHref(), vappTemplate.getHref());
assertEquals(item.getEntity().getType(), vappTemplate.getType()); assertEquals(item.getEntity().getType(), vappTemplate.getType());

View File

@ -161,9 +161,9 @@ public class VmClientLiveTest extends BaseVCloudClientLiveTest {
} }
protected void checkVmOutput(String fooTxtContentsMadeByVMwareTools, String decodedVMwareToolsOutput) { protected void checkVmOutput(String fooTxtContentsMadeByVMwareTools, String decodedVMwareToolsOutput) {
assertEquals(decodedVMwareToolsOutput, script);
// note that vmwaretools throws in \r characters when executing scripts // note that vmwaretools throws in \r characters when executing scripts
assertEquals(fooTxtContentsMadeByVMwareTools, iLoveAscii + "\r\n"); assertEquals(fooTxtContentsMadeByVMwareTools, iLoveAscii + "\r\n");
assertEquals(decodedVMwareToolsOutput, script);
} }
protected IPSocket getSocket(NodeMetadata node) { protected IPSocket getSocket(NodeMetadata node) {

View File

@ -88,8 +88,9 @@ public class ParseVCloudErrorFromHttpResponse implements HttpErrorHandler {
switch (response.getStatusCode()) { switch (response.getStatusCode()) {
case 400: case 400:
if (error != null && error.getMinorErrorCode() != null if (error != null
&& error.getMinorErrorCode() == MinorCode.BUSY_ENTITY) && (error.getMinorErrorCode() != null && error.getMinorErrorCode() == MinorCode.BUSY_ENTITY)
|| (error.getMessage() != null && error.getMessage().indexOf("is not running") != -1))
exception = new IllegalStateException(message, exception); exception = new IllegalStateException(message, exception);
else else
exception = new IllegalArgumentException(message, exception); exception = new IllegalArgumentException(message, exception);

View File

@ -25,6 +25,7 @@ import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.vcloud.VCloudMediaType;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@ -36,23 +37,32 @@ public class ParseVCloudErrorFromHttpResponseTest extends BaseHttpErrorHandlerTe
@Test @Test
public void testGet404SetsResourceNotFoundException() { public void testGet404SetsResourceNotFoundException() {
assertCodeMakes("GET", URI assertCodeMakes("GET", URI.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"), 404,
.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"), "", "", ResourceNotFoundException.class);
404, "", "", ResourceNotFoundException.class);
} }
@Test @Test
public void testDelete404SetsHttpResponseException() { public void testDelete404SetsHttpResponseException() {
assertCodeMakes("DELETE", URI assertCodeMakes("DELETE", URI.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"),
.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"),
404, "", "", HttpResponseException.class); 404, "", "", HttpResponseException.class);
} }
@Test
public void testPOSTNotRunningSetsIllegalStateException() {
assertCodeMakes(
"POST",
URI.create("https://vcenterprise.bluelock.com/api/v1.0/vApp/vapp-138351019/action/undeploy"),
400,
"HTTP/1.1 400 Bad Request",
VCloudMediaType.ERROR_XML,
"<Error xmlns=\"http://www.vmware.com/vcloud/v1\" minorErrorCode=\"BAD_REQUEST\" message=\"The requested operation could not be executed since vApp &quot;adriancolecap-78c&quot; is not running.\" majorErrorCode=\"400\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.vmware.com/vcloud/v1 http://vcenterprise.bluelock.com/api/v1.0/schema/master.xsd\"></Error>\n",
IllegalStateException.class);
}
@Test @Test
public void test401SetsAuthorizationException() { public void test401SetsAuthorizationException() {
assertCodeMakes("GET", URI assertCodeMakes("GET", URI.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"), 401,
.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"), "", "", AuthorizationException.class);
401, "", "", AuthorizationException.class);
} }
@Override @Override

View File

@ -561,7 +561,7 @@ public abstract class BaseComputeServiceLiveTest {
} }
} }
protected int nonBlockDuration = 30 * 1000; protected int nonBlockDurationSeconds = 30;
public void testOptionToNotBlock() throws Exception { public void testOptionToNotBlock() throws Exception {
String group = this.group + "block"; String group = this.group + "block";
@ -577,9 +577,9 @@ public abstract class BaseComputeServiceLiveTest {
Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options); Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options);
NodeMetadata node = getOnlyElement(nodes); NodeMetadata node = getOnlyElement(nodes);
assert node.getState() != NodeState.RUNNING; assert node.getState() != NodeState.RUNNING;
long duration = System.currentTimeMillis() - time; long duration = (System.currentTimeMillis() - time) / 1000;
assert duration < nonBlockDuration : String.format("duration(%d) longer than expected(%d) seconds! ", assert duration < nonBlockDurationSeconds : String.format("duration(%d) longer than expected(%d) seconds! ",
duration / 1000, nonBlockDuration); duration, nonBlockDurationSeconds);
} finally { } finally {
client.destroyNodesMatching(inGroup(group)); client.destroyNodesMatching(inGroup(group));
} }

View File

@ -59,15 +59,21 @@ public abstract class BaseHttpErrorHandlerTest {
protected abstract Class<? extends HttpErrorHandler> getHandlerClass(); protected abstract Class<? extends HttpErrorHandler> getHandlerClass();
protected void assertCodeMakes(String method, URI uri, int statusCode, String message, protected void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
Class<? extends Exception> expected) {
assertCodeMakes(method, uri, statusCode, message, null, content, expected);
}
protected void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
String content, Class<? extends Exception> expected) { String content, Class<? extends Exception> expected) {
HttpErrorHandler function = Guice.createInjector(new SaxParserModule()).getInstance( HttpErrorHandler function = Guice.createInjector(new SaxParserModule()).getInstance(getHandlerClass());
getHandlerClass());
HttpCommand command = createMock(HttpCommand.class); HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = new HttpRequest(method, uri); HttpRequest request = new HttpRequest(method, uri);
HttpResponse response = new HttpResponse(statusCode, message, Payloads.newStringPayload(content)); HttpResponse response = new HttpResponse(statusCode, message, Payloads.newStringPayload(content));
if (contentType != null)
response.getPayload().getContentMetadata().setContentType(contentType);
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce(); expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
command.setException(classEq(expected)); command.setException(classEq(expected));

View File

@ -39,7 +39,7 @@ public class BluelockVCloudDirectorComputeServiceLiveTest extends VCloudComputeS
public BluelockVCloudDirectorComputeServiceLiveTest() { public BluelockVCloudDirectorComputeServiceLiveTest() {
provider = "bluelock-vcdirector"; provider = "bluelock-vcdirector";
// vcloud requires instantiate before deploy, which takes longer than 30 seconds // vcloud requires instantiate before deploy, which takes longer than 30 seconds
nonBlockDuration = 300; nonBlockDurationSeconds = 300;
} }
@Override @Override