Issue 695: Added mount/unmount tools+test+live test to take through power cycles with tools

This commit is contained in:
Jason King 2011-11-24 12:56:59 +00:00
parent 8a3c919009
commit 4b03bb707f
4 changed files with 170 additions and 33 deletions

View File

@ -134,4 +134,24 @@ public interface VirtualMachineAsyncClient {
@JAXBResponseParser @JAXBResponseParser
@ExceptionParser(ReturnNullOnNotFoundOr404.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Task> shutdown(@EndpointParam URI uri); ListenableFuture<Task> shutdown(@EndpointParam URI uri);
/**
* @see VirtualMachineClient#mountTools
*/
@POST
@Path("/tools/action/mount")
@Consumes("application/vnd.tmrk.cloud.task")
@JAXBResponseParser
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Task> mountTools(@EndpointParam URI uri);
/**
* @see VirtualMachineClient#unmountTools
*/
@POST
@Path("/tools/action/unmount")
@Consumes("application/vnd.tmrk.cloud.task")
@JAXBResponseParser
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Task> unmountTools(@EndpointParam URI uri);
} }

View File

@ -84,7 +84,7 @@ public interface VirtualMachineClient {
/** /**
* The Action Virtual Machines Power On call powers on a specified virtual machine. * The Action Virtual Machines Power On call powers on a specified virtual machine.
* If successful, the call returns the task that powered on the virtual machine. * If successful, the call returns the task that powered on the virtual machine.
* Note: To power on requires a <PoweredOn> value of false. * Note: To power on requires a PoweredOn value of false.
* @param uri the uri of the virtual machine * @param uri the uri of the virtual machine
* @return Task * @return Task
*/ */
@ -96,7 +96,7 @@ public interface VirtualMachineClient {
* shutdown requests the virtual machine to end all processes and turn itself off * shutdown requests the virtual machine to end all processes and turn itself off
* when all processes complete. * when all processes complete.
* If successful, the call returns the task that powered off the virtual machine. * If successful, the call returns the task that powered off the virtual machine.
* Note: To power off requires a <PoweredOn> value of true. * Note: To power off requires a PoweredOn value of true.
* @param uri the uri of the virtual machine * @param uri the uri of the virtual machine
* @return Task * @return Task
*/ */
@ -105,7 +105,7 @@ public interface VirtualMachineClient {
/** /**
* The Action Virtual Machines Power Reboot call reboots a specified virtual machine. * The Action Virtual Machines Power Reboot call reboots a specified virtual machine.
* If successful, the call returns the task that rebooted the virtual machine. * If successful, the call returns the task that rebooted the virtual machine.
* Note: To reboot requires a <ToolsStatus> value of Current or OutOfDate and a <PoweredOn> value of true. * Note: To reboot requires a ToolsStatus value of Current or OutOfDate and a PoweredOn value of true.
* @param uri the uri of the virtual machine * @param uri the uri of the virtual machine
* @return Task * @return Task
*/ */
@ -115,10 +115,30 @@ public interface VirtualMachineClient {
* The Action Virtual Machines Power Shutdown call shuts down a specified virtual machine. * The Action Virtual Machines Power Shutdown call shuts down a specified virtual machine.
* Shutdown requests the virtual machine to end all processes and turn itself off when all processes complete whereas power off simply terminates the virtual machine. * Shutdown requests the virtual machine to end all processes and turn itself off when all processes complete whereas power off simply terminates the virtual machine.
* If successful, the call returns the task that shut down the virtual machine. * If successful, the call returns the task that shut down the virtual machine.
* Note: To shutdown requires a <ToolsStatus> value of Current or OutOfDate and a <PoweredOn> value of true. * Note: To shutdown requires a ToolsStatus value of Current or OutOfDate and a PoweredOn value of true.
* @param uri the uri of the virtual machine * @param uri the uri of the virtual machine
* @return Task * @return Task
*/ */
Task shutdown(URI uri); Task shutdown(URI uri);
/**
* The Action Virtual Machines Tools Mount call mounts the virtual volume
* for VMware Tools on a specified virtual machine.
* If successful, the call returns the task that mounted the tools.
* Note: To mount VMware Tools requires a PoweredOn value of true.
* @param uri the uri of the virtual machine
* @return Task
*/
Task mountTools(URI uri);
/**
* The Action Virtual Machines Tools Unmount call unmounts the virtual volume for VMware Tools
* on a specified virtual machine.
* If successful, the call returns the task that unmounted the tools.
* Note: To unmount VMware Tools requires a PoweredOn value of true.
* @param uri the uri of the virtual machine
* @return Task
*/
Task unmountTools(URI uri);
} }

View File

@ -165,6 +165,34 @@ public class VirtualMachineAsyncClientTest extends BaseTerremarkEnterpriseCloudA
checkFilters(httpRequest); checkFilters(httpRequest);
} }
public void testMountTools() throws SecurityException, NoSuchMethodException, IOException, URISyntaxException {
Method method = VirtualMachineAsyncClient.class.getMethod("mountTools", URI.class);
HttpRequest httpRequest = processor.createRequest(method,new URI("/cloudapi/ecloud/virtualmachines/5504"));
assertRequestLineEquals(httpRequest, "POST https://services-beta.enterprisecloud.terremark.com/cloudapi/ecloud/virtualmachines/5504/tools/action/mount HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/vnd.tmrk.cloud.task\nx-tmrk-version: 2011-07-01\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseXMLWithJAXB.class);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testUnmountTools() throws SecurityException, NoSuchMethodException, IOException, URISyntaxException {
Method method = VirtualMachineAsyncClient.class.getMethod("unmountTools", URI.class);
HttpRequest httpRequest = processor.createRequest(method,new URI("/cloudapi/ecloud/virtualmachines/5504"));
assertRequestLineEquals(httpRequest, "POST https://services-beta.enterprisecloud.terremark.com/cloudapi/ecloud/virtualmachines/5504/tools/action/unmount HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/vnd.tmrk.cloud.task\nx-tmrk-version: 2011-07-01\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseXMLWithJAXB.class);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override @Override
protected TypeLiteral<RestAnnotationProcessor<VirtualMachineAsyncClient>> createTypeLiteral() { protected TypeLiteral<RestAnnotationProcessor<VirtualMachineAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<VirtualMachineAsyncClient>>() { return new TypeLiteral<RestAnnotationProcessor<VirtualMachineAsyncClient>>() {

View File

@ -21,6 +21,7 @@ package org.jclouds.tmrk.enterprisecloud.features;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.tmrk.enterprisecloud.domain.Task; import org.jclouds.tmrk.enterprisecloud.domain.Task;
import org.jclouds.tmrk.enterprisecloud.domain.software.ToolsStatus;
import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachine; import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachine;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -51,10 +52,10 @@ public class VirtualMachineClientActionsLiveTest extends BaseTerremarkEnterprise
public void testPowerOn() throws Exception { public void testPowerOn() throws Exception {
vm = client.getVirtualMachine(new URI(vmURI)); vm = client.getVirtualMachine(new URI(vmURI));
assertFalse(vm.isPoweredOn()); assertFalse(vm.isPoweredOn());
Task task = client.powerOn(vm.getHref());
RetryablePredicate retryablePredicate = new RetryablePredicate(taskFinished(), 1000*60); RetryablePredicate retryablePredicate = new RetryablePredicate(taskFinished(), 1000*60);
if (!retryablePredicate.apply(task)) { if (!retryablePredicate.apply(client.powerOn(vm.getHref()))) {
fail("Did not manage to powerOn VM within timeout"); fail("Did not manage to finish powerOn task");
} }
vm = client.getVirtualMachine(vm.getHref()); vm = client.getVirtualMachine(vm.getHref());
@ -62,46 +63,84 @@ public class VirtualMachineClientActionsLiveTest extends BaseTerremarkEnterprise
} }
@Test(dependsOnMethods = "testPowerOn") @Test(dependsOnMethods = "testPowerOn")
public void testShutdown() { public void testMountTools() {
//System.out.println("shutdown"); if (!mountTools(vm.getHref())) {
//Needs tool status Current/OutOfDate fail("Did not manage to finish mount tools task");
//check state }
//shutdown
//wait until done
//power on
} }
@Test(dependsOnMethods = "testShutdown") @Test(dependsOnMethods = "testMountTools")
public void testReboot() { public void testUnmountTools() {
//System.out.println("reboot");
//Needs tool status Current/OutOfDate
//check state
//reboot
//wait until done
}
//@Test(dependsOnMethods = "testReboot")
@Test(dependsOnMethods = "testPowerOn")
public void testPowerOff() {
Task task = client.powerOff(vm.getHref());
RetryablePredicate retryablePredicate = new RetryablePredicate(taskFinished(), 1000*60); RetryablePredicate retryablePredicate = new RetryablePredicate(taskFinished(), 1000*60);
if (!retryablePredicate.apply(task)) { if (!retryablePredicate.apply(client.unmountTools(vm.getHref()))) {
fail("Did not manage to powerOff VM within timeout"); fail("Did not manage finish unmount tools task");
}
//ToolsStatus remains in 'OutOfDate' after un-mounting.
//There is no way to tell, other than to try un-mounting again.
}
@Test(dependsOnMethods = "testUnmountTools")
public void testShutdown() {
//Seems to work as ToolsStatus remains in OutOfDate state
RetryablePredicate retryablePredicate = new RetryablePredicate(taskFinished(), 1000*60);
if (!retryablePredicate.apply(client.shutdown(vm.getHref()))) {
fail("Did not manage to finish shutdown task");
}
// Takes a while to powerOff
retryablePredicate = new RetryablePredicate(poweredOff(), 1000*60);
if (!retryablePredicate.apply(vm.getHref())) {
fail("Did not manage to powerOff after shutdown");
} }
vm = client.getVirtualMachine(vm.getHref()); vm = client.getVirtualMachine(vm.getHref());
assertFalse(vm.isPoweredOn()); assertFalse(vm.isPoweredOn());
} }
@Test(dependsOnMethods = "testShutdown")
public void testReboot() {
RetryablePredicate retryablePredicate = new RetryablePredicate(taskFinished(), 1000*60);
if (!retryablePredicate.apply(client.powerOn(vm.getHref()))) {
fail("Did not manage to finish powerOn task");
}
if (!mountTools(vm.getHref())) {
fail("Did not manage to mount tools");
}
retryablePredicate = new RetryablePredicate(taskFinished(), 1000*60);
if (!retryablePredicate.apply(client.reboot(vm.getHref()))) {
fail("Did not manage to finish reboot task");
}
vm = client.getVirtualMachine(vm.getHref());
assertTrue(vm.isPoweredOn());
}
@Test(dependsOnMethods = "testReboot")
public void testPowerOff() {
RetryablePredicate retryablePredicate = new RetryablePredicate(taskFinished(), 1000*60);
if (!retryablePredicate.apply(client.powerOff(vm.getHref()))) {
fail("Did not manage to finish powerOff task");
}
vm = client.getVirtualMachine(vm.getHref());
assertFalse(vm.isPoweredOn());
}
private boolean mountTools(URI uri) {
// Wait for task to finish AND tools to get into currentOrOutOfDate state
return new RetryablePredicate(taskFinished(), 1000*60).apply(client.mountTools(uri)) &&
new RetryablePredicate(toolsCurrentOrOutOfDate(), 1000*60).apply(uri);
}
// Probably generally useful // Probably generally useful
private Predicate taskFinished() { private Predicate taskFinished() {
return new Predicate<Task>() { return new Predicate<Task>() {
@Override @Override
public boolean apply(@Nullable Task task) { public boolean apply(Task task) {
TaskClient taskClient = context.getApi().getTaskClient(); TaskClient taskClient = context.getApi().getTaskClient();
task = taskClient.getTask(task.getHref()); task = taskClient.getTask(task.getHref());
Task.Status status = task.getStatus(); switch(task.getStatus()) {
switch(status) {
case QUEUED: case QUEUED:
case RUNNING: case RUNNING:
return false; return false;
@ -109,10 +148,40 @@ public class VirtualMachineClientActionsLiveTest extends BaseTerremarkEnterprise
case SUCCESS: case SUCCESS:
return true; return true;
default: default:
throw new RuntimeException("Task Failed:"+task.getHref()+", Status:"+status); throw new RuntimeException("Task Failed:"+task.getHref()+", Status:"+task.getStatus());
} }
} }
}; };
} }
// Probably generally useful
private Predicate toolsCurrentOrOutOfDate() {
return new Predicate<URI>() {
@Override
public boolean apply(URI uri) {
VirtualMachine virtualMachine = client.getVirtualMachine(uri);
ToolsStatus toolsStatus = virtualMachine.getToolsStatus();
switch(toolsStatus) {
case NOT_INSTALLED:
case NOT_RUNNING:
return false;
case CURRENT:
case OUT_OF_DATE:
return true;
default:
throw new RuntimeException("Unable to determine toolsStatus for:"+uri+", ToolsStatus:"+toolsStatus);
}
}
};
}
private Predicate poweredOff() {
return new Predicate<URI>() {
@Override
public boolean apply(URI uri) {
VirtualMachine virtualMachine = client.getVirtualMachine(uri);
return !virtualMachine.isPoweredOn();
}
};
}
} }