openstack-nova: Adding actions to HostAdministration extension

This commit is contained in:
Adam Lowe 2012-05-11 12:37:07 +01:00
parent f790607ffb
commit 5228a14fbb
6 changed files with 441 additions and 26 deletions

View File

@ -22,21 +22,31 @@ import java.util.Set;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import org.jclouds.openstack.filters.AuthenticateRequest; import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v1_1.domain.Host; import org.jclouds.openstack.nova.v1_1.domain.Host;
import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage; import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage;
import org.jclouds.openstack.nova.v1_1.functions.FieldValueResponseParsers.MaintenanceModeDisabledResponseParser;
import org.jclouds.openstack.nova.v1_1.functions.FieldValueResponseParsers.MaintenanceModeEnabledResponseParser;
import org.jclouds.openstack.nova.v1_1.functions.FieldValueResponseParsers.PowerIsRebootResponseParser;
import org.jclouds.openstack.nova.v1_1.functions.FieldValueResponseParsers.PowerIsShutdownResponseParser;
import org.jclouds.openstack.nova.v1_1.functions.FieldValueResponseParsers.PowerIsStartupResponseParser;
import org.jclouds.openstack.nova.v1_1.functions.FieldValueResponseParsers.StatusDisabledResponseParser;
import org.jclouds.openstack.nova.v1_1.functions.FieldValueResponseParsers.StatusEnabledResponseParser;
import org.jclouds.openstack.services.Extension; import org.jclouds.openstack.services.Extension;
import org.jclouds.openstack.services.ServiceType; import org.jclouds.openstack.services.ServiceType;
import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -45,7 +55,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* <p/> * <p/>
* *
* @author Adam Lowe * @author Adam Lowe
* @see SimpleTenantUsageClient * @see HostAdministrationClient
* @see <a href= "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"/> * @see <a href= "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"/>
* @see <a href="http://nova.openstack.org/api_ext" /> * @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.hosts.html" /> * @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.hosts.html" />
@ -53,15 +63,15 @@ import com.google.common.util.concurrent.ListenableFuture;
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.HOSTS) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.HOSTS)
@SkipEncoding({'/', '='}) @SkipEncoding({'/', '='})
@RequestFilters(AuthenticateRequest.class) @RequestFilters(AuthenticateRequest.class)
@Path("/os-hosts")
@Consumes(MediaType.APPLICATION_JSON)
public interface HostAdministrationAsyncClient { public interface HostAdministrationAsyncClient {
/** /**
* @see HostAdministrationClient#listHosts() * @see HostAdministrationClient#listHosts()
*/ */
@GET @GET
@Path("/os-hosts")
@SelectJson("hosts") @SelectJson("hosts")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Host>> listHosts(); ListenableFuture<Set<Host>> listHosts();
@ -69,10 +79,72 @@ public interface HostAdministrationAsyncClient {
* @see HostAdministrationClient#getHostResourceUsage(String) * @see HostAdministrationClient#getHostResourceUsage(String)
*/ */
@GET @GET
@Path("/os-hosts/{id}") @Path("/{id}")
@SelectJson("host") @SelectJson("host")
@Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Set<HostResourceUsage>> getHostResourceUsage(@PathParam("id") String hostId); ListenableFuture<Set<HostResourceUsage>> getHostResourceUsage(@PathParam("id") String hostId);
/**
* @see HostAdministrationClient#enableHost(String)
*/
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}")
@Payload("{\"status\":\"enable\"}")
@ResponseParser(StatusEnabledResponseParser.class)
ListenableFuture<Boolean> enableHost(@PathParam("id") String hostId);
/**
* @see HostAdministrationClient#disableHost(String)
*/
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}")
@Payload("{\"status\":\"disable\"}")
@ResponseParser(StatusDisabledResponseParser.class)
ListenableFuture<Boolean> disableHost(@PathParam("id") String hostId);
/**
* @see HostAdministrationClient#startHostMaintenance(String)
*/
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}")
@Payload("{\"maintenance_mode\":\"enable\"}")
@ResponseParser(MaintenanceModeEnabledResponseParser.class)
ListenableFuture<Boolean> startHostMaintenance(@PathParam("id") String hostId);
/**
* @see HostAdministrationClient#stopHostMaintenance(String)
*/
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}")
@Payload("{\"maintenance_mode\":\"disable\"}")
@ResponseParser(MaintenanceModeDisabledResponseParser.class)
ListenableFuture<Boolean> stopHostMaintenance(@PathParam("id") String hostId);
/**
* @see HostAdministrationClient#startupHost(String)
*/
@GET
@Path("/{id}/startup")
@ResponseParser(PowerIsStartupResponseParser.class)
ListenableFuture<Boolean> startupHost(@PathParam("id") String hostId);
/**
* @see HostAdministrationClient#shutdownHost(String)
*/
@GET
@Path("/{id}/shutdown")
@ResponseParser(PowerIsShutdownResponseParser.class)
ListenableFuture<Boolean> shutdownHost(@PathParam("id") String hostId);
/**
* @see HostAdministrationClient#rebootHost(String)
*/
@GET
@Path("/{id}/reboot")
@ResponseParser(PowerIsRebootResponseParser.class)
ListenableFuture<Boolean> rebootHost(@PathParam("id") String hostId);
} }

View File

@ -21,8 +21,6 @@ package org.jclouds.openstack.nova.v1_1.extensions;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.ws.rs.PathParam;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.openstack.nova.v1_1.domain.Host; import org.jclouds.openstack.nova.v1_1.domain.Host;
import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage; import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage;
@ -32,7 +30,6 @@ import org.jclouds.openstack.services.ServiceType;
/** /**
* Provides asynchronous access to Host Administration features via the REST API. * Provides asynchronous access to Host Administration features via the REST API.
* <p/> * <p/>
* TODO reboot, shutdown, startup, update
* *
* @author Adam Lowe * @author Adam Lowe
* @see HostAdministrationAsyncClient * @see HostAdministrationAsyncClient
@ -43,14 +40,67 @@ public interface HostAdministrationClient {
/** /**
* Returns the list of hosts * Returns the list of hosts
*
* @return the usage information * @return the usage information
*/ */
Set<Host> listHosts(); Set<Host> listHosts();
/** /**
* Retrieves the physical/usage resource on a specific host * Retrieves the physical/usage resource on a specific host
*
* @return the usage information * @return the usage information
*/ */
Set<HostResourceUsage> getHostResourceUsage(@PathParam("id") String hostId); Set<HostResourceUsage> getHostResourceUsage(String hostId);
/**
* Allow the specified host to accept new instances.
*
* @return true if successful
*/
Boolean enableHost(String hostId);
/**
* Prevent the specified host from accepting new instances.
*
* @return true if successful
*/
Boolean disableHost(String hostId);
/**
* Start host maintenance window.
* <p/>
* Note: this triggers guest VMs evacuation.
*
* @return true if successful
*/
Boolean startHostMaintenance(String hostId);
/**
* Stop host maintenance window.
*
* @return true if successful
*/
Boolean stopHostMaintenance(String hostId);
/**
* Startup a host.
*
* @return true if successful
*/
Boolean startupHost(String hostId);
/**
* Shutdown a host.
*
* @return true if successful
*/
Boolean shutdownHost(String hostId);
/**
* Reboot a host.
*
* @return true if successful
*/
Boolean rebootHost(String hostId);
} }

View File

@ -0,0 +1,89 @@
package org.jclouds.openstack.nova.v1_1.functions;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
import org.jclouds.json.internal.GsonWrapper;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
/**
* Parsers for extracting a single field value from a response and comparing it to an expected value
*/
public class FieldValueResponseParsers {
@Singleton
public static class StatusEnabledResponseParser extends FieldValueResponseParser<String> {
@Inject
public StatusEnabledResponseParser(GsonWrapper wrapper) {
super(wrapper, "status", "enabled");
}
}
@Singleton
public static class StatusDisabledResponseParser extends FieldValueResponseParser<String> {
@Inject
public StatusDisabledResponseParser(GsonWrapper wrapper) {
super(wrapper, "status", "disabled");
}
}
@Singleton
public static class MaintenanceModeEnabledResponseParser extends FieldValueResponseParser<String> {
@Inject
public MaintenanceModeEnabledResponseParser(GsonWrapper wrapper) {
super(wrapper, "maintenance_mode", "on_maintenance");
}
}
@Singleton
public static class MaintenanceModeDisabledResponseParser extends FieldValueResponseParser<String> {
@Inject
public MaintenanceModeDisabledResponseParser(GsonWrapper wrapper) {
super(wrapper, "maintenance_mode", "off_maintenance");
}
}
@Singleton
public static class PowerIsStartupResponseParser extends FieldValueResponseParser<String> {
@Inject
public PowerIsStartupResponseParser(GsonWrapper wrapper) {
super(wrapper, "power_action", "startup");
}
}
@Singleton
public static class PowerIsShutdownResponseParser extends FieldValueResponseParser<String> {
@Inject
public PowerIsShutdownResponseParser(GsonWrapper wrapper) {
super(wrapper, "power_action", "shutdown");
}
}
@Singleton
public static class PowerIsRebootResponseParser extends FieldValueResponseParser<String> {
@Inject
public PowerIsRebootResponseParser(GsonWrapper wrapper) {
super(wrapper, "power_action", "reboot");
}
}
public static abstract class FieldValueResponseParser<T> implements Function<HttpResponse, Boolean> {
private final T expectedValue;
private final ParseFirstJsonValueNamed<T> valueParser;
public FieldValueResponseParser(GsonWrapper wrapper, String fieldName, T expectedValue) {
valueParser = new ParseFirstJsonValueNamed<T>(wrapper, new TypeLiteral<T>() {
}, fieldName);
this.expectedValue = expectedValue;
}
@Override
public Boolean apply(HttpResponse response) {
return Objects.equal(expectedValue, valueParser.apply(response));
}
}
}

View File

@ -19,6 +19,8 @@
package org.jclouds.openstack.nova.v1_1.extensions; package org.jclouds.openstack.nova.v1_1.extensions;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.net.URI; import java.net.URI;
import java.util.Set; import java.util.Set;
@ -30,6 +32,7 @@ import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.domain.Host; import org.jclouds.openstack.nova.v1_1.domain.Host;
import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage; import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest; import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
@ -37,7 +40,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
/** /**
* Tests HostAdministrationClient guice wiring and parsing * Tests HostAdministrationClient guice wiring and parsing (including the Response parsers in FieldValueResponseParsers)
* *
* @author Adam Lowe * @author Adam Lowe
*/ */
@ -45,7 +48,7 @@ import com.google.common.collect.Iterables;
public class HostAdministrationClientExpectTest extends BaseNovaClientExpectTest { public class HostAdministrationClientExpectTest extends BaseNovaClientExpectTest {
public void testList() throws Exception { public void testList() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts"); URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword, HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
@ -63,7 +66,7 @@ public class HostAdministrationClientExpectTest extends BaseNovaClientExpectTest
assertEquals(host, expected); assertEquals(host, expected);
} }
public void testGet() throws Exception { public void testGet() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/xyz"); URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/xyz");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword, HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
@ -81,4 +84,140 @@ public class HostAdministrationClientExpectTest extends BaseNovaClientExpectTest
assertEquals(client.getHostResourceUsage("xyz"), expected); assertEquals(client.getHostResourceUsage("xyz"), expected);
} }
public void testEnableHost() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("PUT").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.payload(payloadFromStringWithContentType("{\"status\":\"enable\"}", MediaType.APPLICATION_JSON))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"host\":\"ubuntu\",\"status\":\"enabled\"}", MediaType.APPLICATION_JSON))
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.enableHost("ubuntu"));
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testEnableHostFailNotFound() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("PUT").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.payload(payloadFromStringWithContentType("{\"status\":\"enable\"}", MediaType.APPLICATION_JSON))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(404)
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
client.enableHost("ubuntu");
}
public void testEnableHostFailNotEnabled() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("PUT").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.payload(payloadFromStringWithContentType("{\"status\":\"enable\"}", MediaType.APPLICATION_JSON))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"host\":\"ubuntu\",\"status\":\"disabled\"}", MediaType.APPLICATION_JSON))
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertFalse(client.enableHost("ubuntu"));
}
public void testDisableHost() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("PUT").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.payload(payloadFromStringWithContentType("{\"status\":\"disable\"}", MediaType.APPLICATION_JSON))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"host\":\"ubuntu\",\"status\":\"disabled\"}", MediaType.APPLICATION_JSON))
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.disableHost("ubuntu"));
}
public void testStartMaintenance() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("PUT").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.payload(payloadFromStringWithContentType("{\"maintenance_mode\":\"enable\"}", MediaType.APPLICATION_JSON))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"host\":\"ubuntu\",\"maintenance_mode\":\"on_maintenance\"}", MediaType.APPLICATION_JSON))
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.startHostMaintenance("ubuntu"));
}
public void testStopMaintenance() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("PUT").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.payload(payloadFromStringWithContentType("{\"maintenance_mode\":\"disable\"}", MediaType.APPLICATION_JSON))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"host\":\"ubuntu\",\"maintenance_mode\":\"off_maintenance\"}", MediaType.APPLICATION_JSON))
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.stopHostMaintenance("ubuntu"));
}
public void testStartupHost() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu/startup");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"host\":\"ubuntu\",\"power_action\":\"startup\"}", MediaType.APPLICATION_JSON))
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.startupHost("ubuntu"));
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testStartupHostFailNotFound() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu/startup");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(404).build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.startupHost("ubuntu"));
}
public void testStartupHostFailWrongActionInProgress() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu/startup");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"host\":\"ubuntu\",\"power_action\":\"shutdown\"}", MediaType.APPLICATION_JSON))
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertFalse(client.startupHost("ubuntu"));
}
public void testShutdownHost() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu/shutdown");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"host\":\"ubuntu\",\"power_action\":\"shutdown\"}", MediaType.APPLICATION_JSON))
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.shutdownHost("ubuntu"));
}
public void testRebootHost() {
URI endpoint = URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-hosts/ubuntu/reboot");
HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken))
.endpoint(endpoint).build(),
HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"host\":\"ubuntu\",\"power_action\":\"reboot\"}", MediaType.APPLICATION_JSON))
.build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get();
assertTrue(client.rebootHost("ubuntu"));
}
} }

View File

@ -20,28 +20,50 @@ package org.jclouds.openstack.nova.v1_1.extensions;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.Set; import java.util.Set;
import org.jclouds.openstack.nova.v1_1.domain.Host; import org.jclouds.openstack.nova.v1_1.domain.Host;
import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage; import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest; import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Objects;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
/** /**
* Tests behavior of HostAdministrationClient * Tests behavior of HostAdministrationClient
* *
* @author Adam Lowe * @author Adam Lowe
*/ */
@Test(groups = "live", testName = "HostAdministrationClientLiveTest") @Test(groups = "live", testName = "HostAdministrationClientLiveTest", singleThreaded = true)
public class HostAdministrationClientLiveTest extends BaseNovaClientLiveTest { public class HostAdministrationClientLiveTest extends BaseNovaClientLiveTest {
private Optional<HostAdministrationClient> optClient = Optional.absent();
Predicate<Host> isComputeHost = new Predicate<Host>() {
@Override
public boolean apply(Host input) {
return Objects.equal("compute", input.getService());
}
};
@BeforeGroups(groups = {"integration", "live"})
@Override
public void setupContext() {
super.setupContext();
if (identity.endsWith(":admin")) {
String zone = Iterables.getLast(novaContext.getApi().getConfiguredZones(), "nova");
optClient = novaContext.getApi().getHostAdministrationExtensionForZone(zone);
}
}
public void testListAndGet() throws Exception { public void testListAndGet() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) { if (optClient.isPresent()) {
Optional<HostAdministrationClient> optClient = novaContext.getApi().getHostAdministrationExtensionForZone(zoneId);
if (optClient.isPresent() && identity.endsWith(":admin")) {
HostAdministrationClient client = optClient.get(); HostAdministrationClient client = optClient.get();
Set<Host> hosts = client.listHosts(); Set<Host> hosts = client.listHosts();
assertNotNull(hosts); assertNotNull(hosts);
@ -53,6 +75,44 @@ public class HostAdministrationClientLiveTest extends BaseNovaClientLiveTest {
} }
} }
} }
@Test(enabled = false)
public void testEnableDisable() throws Exception {
if (optClient.isPresent()) {
HostAdministrationClient client = optClient.get();
Host host = Iterables.find(client.listHosts(), isComputeHost);
assertTrue(client.disableHost(host.getName()));
assertTrue(client.enableHost(host.getName()));
}
} }
@Test(enabled = false)
public void testMaintenanceMode() throws Exception {
if (optClient.isPresent()) {
HostAdministrationClient client = optClient.get();
Host host = Iterables.find(client.listHosts(), isComputeHost);
assertTrue(client.startHostMaintenance(host.getName()));
assertTrue(client.stopHostMaintenance(host.getName()));
}
}
@Test(enabled = false)
public void testReboot() throws Exception {
if (optClient.isPresent()) {
HostAdministrationClient client = optClient.get();
Host host = Iterables.find(client.listHosts(), isComputeHost);
assertTrue(client.rebootHost(host.getName()));
}
}
@Test(enabled = false)
public void testShutdownAndStartup() throws Exception {
if (optClient.isPresent()) {
HostAdministrationClient client = optClient.get();
Host host = Iterables.find(client.listHosts(), isComputeHost);
assertTrue(client.shutdownHost(host.getName()));
assertTrue(client.startupHost(host.getName()));
}
}
} }

View File

@ -89,4 +89,9 @@ public class BaseNovaExpectTest<T> extends BaseRestClientExpectTest<T> {
protected HttpResponse.Builder standardResponseBuilder(int status) { protected HttpResponse.Builder standardResponseBuilder(int status) {
return HttpResponse.builder().statusCode(status); return HttpResponse.builder().statusCode(status);
} }
@Override
protected HttpRequestComparisonType compareHttpRequestAsType(HttpRequest input) {
return HttpRequestComparisonType.JSON;
}
} }