Issue 695: Methods to powerOn/powerOff/shutdown/reboot a VM

This commit is contained in:
Jason King 2011-11-24 11:01:37 +00:00
parent 835ea8bb57
commit 8a3c919009
4 changed files with 259 additions and 1 deletions

View File

@ -22,6 +22,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.annotations.*; import org.jclouds.rest.annotations.*;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.tmrk.enterprisecloud.domain.Task;
import org.jclouds.tmrk.enterprisecloud.domain.hardware.HardwareConfiguration; import org.jclouds.tmrk.enterprisecloud.domain.hardware.HardwareConfiguration;
import org.jclouds.tmrk.enterprisecloud.domain.network.AssignedIpAddresses; import org.jclouds.tmrk.enterprisecloud.domain.network.AssignedIpAddresses;
import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachine; import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachine;
@ -31,6 +32,8 @@ import org.jclouds.tmrk.enterprisecloud.functions.ReturnEmptyVirtualMachinesOnNo
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.net.URI; import java.net.URI;
/** /**
@ -91,4 +94,44 @@ public interface VirtualMachineAsyncClient {
@JAXBResponseParser @JAXBResponseParser
@ExceptionParser(ReturnNullOnNotFoundOr404.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<HardwareConfiguration> getHardwareConfiguration(@EndpointParam URI uri); ListenableFuture<HardwareConfiguration> getHardwareConfiguration(@EndpointParam URI uri);
/**
* @see VirtualMachineClient#powerOn
*/
@POST
@Path("/action/powerOn")
@Consumes("application/vnd.tmrk.cloud.task")
@JAXBResponseParser
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Task> powerOn(@EndpointParam URI uri);
/**
* @see VirtualMachineClient#powerOff
*/
@POST
@Path("/action/powerOff")
@Consumes("application/vnd.tmrk.cloud.task")
@JAXBResponseParser
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Task> powerOff(@EndpointParam URI uri);
/**
* @see VirtualMachineClient#reboot
*/
@POST
@Path("/action/reboot")
@Consumes("application/vnd.tmrk.cloud.task")
@JAXBResponseParser
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Task> reboot(@EndpointParam URI uri);
/**
* @see VirtualMachineClient#shutdown
*/
@POST
@Path("/action/shutdown")
@Consumes("application/vnd.tmrk.cloud.task")
@JAXBResponseParser
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Task> shutdown(@EndpointParam URI uri);
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.tmrk.enterprisecloud.features; package org.jclouds.tmrk.enterprisecloud.features;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.tmrk.enterprisecloud.domain.Task;
import org.jclouds.tmrk.enterprisecloud.domain.hardware.HardwareConfiguration; import org.jclouds.tmrk.enterprisecloud.domain.hardware.HardwareConfiguration;
import org.jclouds.tmrk.enterprisecloud.domain.network.AssignedIpAddresses; import org.jclouds.tmrk.enterprisecloud.domain.network.AssignedIpAddresses;
import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachine; import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachine;
@ -80,4 +81,44 @@ public interface VirtualMachineClient {
*/ */
HardwareConfiguration getHardwareConfiguration(URI uri); HardwareConfiguration getHardwareConfiguration(URI uri);
/**
* 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.
* Note: To power on requires a <PoweredOn> value of false.
* @param uri the uri of the virtual machine
* @return Task
*/
Task powerOn(URI uri);
/**
* The Action Virtual Machines Power Off call powers off a specified virtual machine.
* Power off simply terminates the virtual machine whereas
* shutdown requests the virtual machine to end all processes and turn itself off
* when all processes complete.
* If successful, the call returns the task that powered off the virtual machine.
* Note: To power off requires a <PoweredOn> value of true.
* @param uri the uri of the virtual machine
* @return Task
*/
Task powerOff(URI uri);
/**
* The Action Virtual Machines Power Reboot call reboots a specified 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.
* @param uri the uri of the virtual machine
* @return Task
*/
Task reboot(URI uri);
/**
* 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.
* 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.
* @param uri the uri of the virtual machine
* @return Task
*/
Task shutdown(URI uri);
} }

View File

@ -32,7 +32,7 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
/** /**
* Tests annotation parsing of {@code TaskAsyncClient} * Tests annotation parsing of {@code VirtualMachineAsyncClient}
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ -109,6 +109,62 @@ public class VirtualMachineAsyncClientTest extends BaseTerremarkEnterpriseCloudA
checkFilters(httpRequest); checkFilters(httpRequest);
} }
public void testPowerOn() throws SecurityException, NoSuchMethodException, IOException, URISyntaxException {
Method method = VirtualMachineAsyncClient.class.getMethod("powerOn", 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/action/powerOn 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 testPowerOff() throws SecurityException, NoSuchMethodException, IOException, URISyntaxException {
Method method = VirtualMachineAsyncClient.class.getMethod("powerOff", 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/action/powerOff 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 testReboot() throws SecurityException, NoSuchMethodException, IOException, URISyntaxException {
Method method = VirtualMachineAsyncClient.class.getMethod("reboot", 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/action/reboot 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 testShutdown() throws SecurityException, NoSuchMethodException, IOException, URISyntaxException {
Method method = VirtualMachineAsyncClient.class.getMethod("shutdown", 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/action/shutdown 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

@ -0,0 +1,118 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.tmrk.enterprisecloud.features;
import com.google.common.base.Predicate;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.tmrk.enterprisecloud.domain.Task;
import org.jclouds.tmrk.enterprisecloud.domain.vm.VirtualMachine;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import javax.annotation.Nullable;
import java.net.URI;
import static org.testng.Assert.*;
/**
* Tests behavior of {@code VirtualMachineClient} actions
* @author Jason King
*/
@Test(groups = "live", testName = "VirtualMachineClientActionsLiveTest")
public class VirtualMachineClientActionsLiveTest extends BaseTerremarkEnterpriseCloudClientLiveTest {
@BeforeGroups(groups = { "live" })
public void setupClient() {
super.setupClient();
client = context.getApi().getVirtualMachineClient();
}
//TODO: Need a create call to make this not dependent on existing vm
private static final String vmURI = "/cloudapi/ecloud/virtualmachines/5504";
private VirtualMachineClient client;
private VirtualMachine vm;
public void testPowerOn() throws Exception {
vm = client.getVirtualMachine(new URI(vmURI));
assertFalse(vm.isPoweredOn());
Task task = client.powerOn(vm.getHref());
RetryablePredicate retryablePredicate = new RetryablePredicate(taskFinished(), 1000*60);
if (!retryablePredicate.apply(task)) {
fail("Did not manage to powerOn VM within timeout");
}
vm = client.getVirtualMachine(vm.getHref());
assertTrue(vm.isPoweredOn());
}
@Test(dependsOnMethods = "testPowerOn")
public void testShutdown() {
//System.out.println("shutdown");
//Needs tool status Current/OutOfDate
//check state
//shutdown
//wait until done
//power on
}
@Test(dependsOnMethods = "testShutdown")
public void testReboot() {
//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);
if (!retryablePredicate.apply(task)) {
fail("Did not manage to powerOff VM within timeout");
}
vm = client.getVirtualMachine(vm.getHref());
assertFalse(vm.isPoweredOn());
}
// Probably generally useful
private Predicate taskFinished() {
return new Predicate<Task>() {
@Override
public boolean apply(@Nullable Task task) {
TaskClient taskClient = context.getApi().getTaskClient();
task = taskClient.getTask(task.getHref());
Task.Status status = task.getStatus();
switch(status) {
case QUEUED:
case RUNNING:
return false;
case COMPLETE:
case SUCCESS:
return true;
default:
throw new RuntimeException("Task Failed:"+task.getHref()+", Status:"+status);
}
}
};
}
}