JCLOUDS-40: Unasync OpenStack Nova API

This commit is contained in:
Jeremy Daggett 2014-03-21 08:48:15 -07:00 committed by Jeremy Daggett
parent 086fb9c728
commit 801aecafea
60 changed files with 1783 additions and 3639 deletions

View File

@ -17,25 +17,40 @@
package org.jclouds.openstack.v2_0.features; package org.jclouds.openstack.v2_0.features;
import java.util.Set; import java.util.Set;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.v2_0.domain.Extension; import org.jclouds.openstack.v2_0.domain.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
/** /**
* Provides asynchronous access to Extensions via their REST API. * Provides asynchronous access to Extensions via their REST API.
* <p/>
*
* @see ExtensionAsyncApi
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* />
*/ */
@RequestFilters(AuthenticateRequest.class)
public interface ExtensionApi { public interface ExtensionApi {
/** /**
* List all available extensions * Lists all available extensions
* *
* @return all extensions * @return all extensions
*/ */
Set<? extends Extension> list(); @Named("extension:list")
@GET
@SelectJson("extensions")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/extensions")
@Fallback(EmptySetOnNotFoundOr404.class)
Set<Extension> list();
/** /**
* Extensions may also be queried individually by their unique alias. * Extensions may also be queried individually by their unique alias.
@ -44,6 +59,11 @@ public interface ExtensionApi {
* id of the extension * id of the extension
* @return extension or null if not found * @return extension or null if not found
*/ */
Extension get(String alias); @Named("extension:get")
@GET
@SelectJson("extension")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/extensions/{alias}")
@Fallback(NullOnNotFoundOr404.class)
Extension get(@PathParam("alias") String id);
} }

View File

@ -18,6 +18,7 @@ package org.jclouds.openstack.nova.v2_0;
import java.io.Closeable; import java.io.Closeable;
import java.util.Set; import java.util.Set;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Zone; import org.jclouds.location.Zone;
import org.jclouds.location.functions.ZoneToEndpoint; import org.jclouds.location.functions.ZoneToEndpoint;
@ -48,12 +49,9 @@ import com.google.common.base.Optional;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
* Provides synchronous access to Nova. * Provides access to the OpenStack Compute (Nova) API.
* <p/> * <p/>
* *
* @see NovaAsyncApi
* @see <a href="http://docs.openstack.org/api/openstack-compute/1.1/content/"
* />
*/ */
public interface NovaApi extends Closeable { public interface NovaApi extends Closeable {
/** /**
@ -65,133 +63,133 @@ public interface NovaApi extends Closeable {
Set<String> getConfiguredZones(); Set<String> getConfiguredZones();
/** /**
* Provides synchronous access to availability zone features * Provides access to Server features.
*/
@Delegate
Optional<? extends AvailabilityZoneApi> getAvailabilityZoneApi(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Server features.
*/ */
@Delegate @Delegate
ServerApi getServerApiForZone( ServerApi getServerApiForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Flavor features. * Provides access to Flavor features.
*/ */
@Delegate @Delegate
FlavorApi getFlavorApiForZone( FlavorApi getFlavorApiForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Extension features. * Provides access to Extension features.
*/ */
@Delegate @Delegate
ExtensionApi getExtensionApiForZone( ExtensionApi getExtensionApiForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Image features. * Provides access to Image features.
*/ */
@Delegate @Delegate
ImageApi getImageApiForZone( ImageApi getImageApiForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Floating IP features. * Provides access to availability zone features
*/
@Delegate
Optional<? extends AvailabilityZoneApi> getAvailabilityZoneApi(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides access to Floating IP features.
*/ */
@Delegate @Delegate
Optional<? extends FloatingIPApi> getFloatingIPExtensionForZone( Optional<? extends FloatingIPApi> getFloatingIPExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Security Group features. * Provides access to Security Group features.
*/ */
@Delegate @Delegate
Optional<? extends SecurityGroupApi> getSecurityGroupExtensionForZone( Optional<? extends SecurityGroupApi> getSecurityGroupExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Key Pair features. * Provides access to Key Pair features.
*/ */
@Delegate @Delegate
Optional<? extends KeyPairApi> getKeyPairExtensionForZone( Optional<? extends KeyPairApi> getKeyPairExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Host Administration features. * Provides access to Host Administration features.
*/ */
@Delegate @Delegate
Optional<? extends HostAdministrationApi> getHostAdministrationExtensionForZone( Optional<? extends HostAdministrationApi> getHostAdministrationExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Simple Tenant Usage features. * Provides access to Simple Tenant Usage features.
*/ */
@Delegate @Delegate
Optional<? extends SimpleTenantUsageApi> getSimpleTenantUsageExtensionForZone( Optional<? extends SimpleTenantUsageApi> getSimpleTenantUsageExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Virtual Interface features. * Provides access to Virtual Interface features.
*/ */
@Delegate @Delegate
Optional<? extends VirtualInterfaceApi> getVirtualInterfaceExtensionForZone( Optional<? extends VirtualInterfaceApi> getVirtualInterfaceExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Server Extra Data features. * Provides access to Server Extra Data features.
*/ */
@Delegate @Delegate
Optional<? extends ServerWithSecurityGroupsApi> getServerWithSecurityGroupsExtensionForZone( Optional<? extends ServerWithSecurityGroupsApi> getServerWithSecurityGroupsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Server Admin Actions features. * Provides access to Server Admin Actions features.
*/ */
@Delegate @Delegate
Optional<? extends ServerAdminApi> getServerAdminExtensionForZone( Optional<? extends ServerAdminApi> getServerAdminExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Aggregate features. * Provides access to Aggregate features.
*/ */
@Delegate @Delegate
Optional<? extends HostAggregateApi> getHostAggregateExtensionForZone( Optional<? extends HostAggregateApi> getHostAggregateExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Flavor extra specs features. * Provides access to Flavor extra specs features.
*/ */
@Delegate @Delegate
Optional<? extends FlavorExtraSpecsApi> getFlavorExtraSpecsExtensionForZone( Optional<? extends FlavorExtraSpecsApi> getFlavorExtraSpecsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Quota features. * Provides access to Quota features.
*/ */
@Delegate @Delegate
Optional<? extends QuotaApi> getQuotaExtensionForZone( Optional<? extends QuotaApi> getQuotaExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Volume features. * Provides access to Volume features.
*/ */
@Delegate @Delegate
Optional<? extends VolumeApi> getVolumeExtensionForZone( Optional<? extends VolumeApi> getVolumeExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Volume Attachment features. * Provides access to Volume Attachment features.
*/ */
@Delegate @Delegate
Optional<? extends VolumeAttachmentApi> getVolumeAttachmentExtensionForZone( Optional<? extends VolumeAttachmentApi> getVolumeAttachmentExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/** /**
* Provides synchronous access to Volume Type features. * Provides access to Volume Type features.
*/ */
@Delegate @Delegate
Optional<? extends VolumeTypeApi> getVolumeTypeExtensionForZone( Optional<? extends VolumeTypeApi> getVolumeTypeExtensionForZone(
@ -203,5 +201,4 @@ public interface NovaApi extends Closeable {
@Delegate @Delegate
Optional<? extends ConsolesApi> getConsolesExtensionForZone( Optional<? extends ConsolesApi> getConsolesExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
} }

View File

@ -28,33 +28,23 @@ import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.openstack.keystone.v2_0.config.AuthenticationApiModule;
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
import org.jclouds.openstack.nova.v2_0.compute.config.NovaComputeServiceContextModule; import org.jclouds.openstack.nova.v2_0.compute.config.NovaComputeServiceContextModule;
import org.jclouds.openstack.nova.v2_0.config.NovaHttpApiModule;
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule; import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
import org.jclouds.openstack.nova.v2_0.config.NovaRestClientModule;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.rest.internal.BaseRestApiMetadata; import org.jclouds.rest.internal.BaseHttpApiMetadata;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
* Implementation of {@link ApiMetadata} for Nova 2.0 API * Implementation of {@link org.jclouds.apis.ApiMetadata} for Nova 2.0 API
*/ */
public class NovaApiMetadata extends BaseRestApiMetadata { public class NovaApiMetadata extends BaseHttpApiMetadata<NovaApi> {
/**
* @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(NovaApi.class)} as
* {@link NovaAsyncApi} interface will be removed in jclouds 1.7.
*/
@Deprecated
public static final TypeToken<org.jclouds.rest.RestContext<NovaApi, NovaAsyncApi>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<NovaApi, NovaAsyncApi>>() {
private static final long serialVersionUID = 1L;
};
@Override @Override
public Builder toBuilder() { public Builder toBuilder() {
@ -70,7 +60,7 @@ public class NovaApiMetadata extends BaseRestApiMetadata {
} }
public static Properties defaultProperties() { public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties(); Properties properties = BaseHttpApiMetadata.defaultProperties();
// auth fail can happen while cloud-init applies keypair updates // auth fail can happen while cloud-init applies keypair updates
properties.setProperty("jclouds.ssh.max-retries", "7"); properties.setProperty("jclouds.ssh.max-retries", "7");
properties.setProperty("jclouds.ssh.retry-auth", "true"); properties.setProperty("jclouds.ssh.retry-auth", "true");
@ -86,27 +76,25 @@ public class NovaApiMetadata extends BaseRestApiMetadata {
return properties; return properties;
} }
public static class Builder extends BaseRestApiMetadata.Builder<Builder> { public static class Builder extends BaseHttpApiMetadata.Builder<NovaApi, Builder> {
@SuppressWarnings("deprecation")
protected Builder() { protected Builder() {
super(NovaApi.class, NovaAsyncApi.class);
id("openstack-nova") id("openstack-nova")
.name("OpenStack Nova Diablo+ API") .name("OpenStack Nova Diablo+ API")
.identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant") .identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant")
.credentialName("${password}") .credentialName("${password}")
.endpointName("KeyStone base url ending in /v2.0/") .endpointName("Keystone base url ending in /v2.0/")
.documentation(URI.create("http://api.openstack.org/")) .documentation(URI.create("http://api.openstack.org/"))
.version("1.1") .version("1.1")
.defaultEndpoint("http://localhost:5000/v2.0/") .defaultEndpoint("http://localhost:5000/v2.0/")
.defaultProperties(NovaApiMetadata.defaultProperties()) .defaultProperties(NovaApiMetadata.defaultProperties())
.view(typeToken(ComputeServiceContext.class)) .view(typeToken(ComputeServiceContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>builder() .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(MappedAuthenticationApiModule.class) .add(AuthenticationApiModule.class)
.add(KeystoneAuthenticationModule.class) .add(KeystoneAuthenticationModule.class)
.add(ZoneModule.class) .add(ZoneModule.class)
.add(NovaParserModule.class) .add(NovaParserModule.class)
.add(NovaRestClientModule.class) .add(NovaHttpApiModule.class)
.add(NovaComputeServiceContextModule.class).build()); .add(NovaComputeServiceContextModule.class).build());
} }

View File

@ -1,213 +0,0 @@
/*
* 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.openstack.nova.v2_0;
import java.io.Closeable;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Zone;
import org.jclouds.location.functions.ZoneToEndpoint;
import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.ConsolesAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.HostAdministrationAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.HostAggregateAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.KeyPairAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.QuotaAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.ServerAdminAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.ServerWithSecurityGroupsAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.SimpleTenantUsageAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.VirtualInterfaceAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAttachmentAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.VolumeTypeAsyncApi;
import org.jclouds.openstack.nova.v2_0.features.FlavorAsyncApi;
import org.jclouds.openstack.nova.v2_0.features.ImageAsyncApi;
import org.jclouds.openstack.nova.v2_0.features.ServerAsyncApi;
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
import com.google.common.base.Optional;
import com.google.inject.Provides;
/**
* Provides asynchronous access to Nova via their REST API.
* <p/>
*
* @see NovaApi
* @see <a href="http://docs.openstack.org/api/openstack-compute/1.1/content/"
* />
* @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(NovaApi.class)} as
* {@link NovaAsyncApi} interface will be removed in jclouds 1.7.
*/
@Deprecated
public interface NovaAsyncApi extends Closeable {
/**
*
* @return the Zone codes configured
*/
@Provides
@Zone
Set<String> getConfiguredZones();
/**
* Provides asynchronous access to availability zone features
*/
@Delegate
Optional<? extends AvailabilityZoneAsyncApi> getAvailabilityZoneApi(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Server features.
*/
@Delegate
ServerAsyncApi getServerApiForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Flavor features.
*/
@Delegate
FlavorAsyncApi getFlavorApiForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Extension features.
*/
@Delegate
ExtensionAsyncApi getExtensionApiForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Image features.
*/
@Delegate
ImageAsyncApi getImageApiForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Floating IP features.
*/
@Delegate
Optional<? extends FloatingIPAsyncApi> getFloatingIPExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Security Group features.
*/
@Delegate
Optional<? extends SecurityGroupAsyncApi> getSecurityGroupExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Key Pair features.
*/
@Delegate
Optional<? extends KeyPairAsyncApi> getKeyPairExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Host Administration features.
*/
@Delegate
Optional<? extends HostAdministrationAsyncApi> getHostAdministrationExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Simple Tenant Usage features.
*/
@Delegate
Optional<? extends SimpleTenantUsageAsyncApi> getSimpleTenantUsageExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Virtual Interface features.
*/
@Delegate
Optional<? extends VirtualInterfaceAsyncApi> getVirtualInterfaceExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Server Extra Data features.
*/
@Delegate
Optional<? extends ServerWithSecurityGroupsAsyncApi> getServerWithSecurityGroupsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Server Admin Actions features.
*/
@Delegate
Optional<? extends ServerAdminAsyncApi> getServerAdminExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to HostAggregate features.
*/
@Delegate
Optional<? extends HostAggregateAsyncApi> getHostAggregateExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Flavor extra specs features.
*/
@Delegate
Optional<? extends FlavorExtraSpecsAsyncApi> getFlavorExtraSpecsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Quota features.
*/
@Delegate
Optional<? extends QuotaAsyncApi> getQuotaExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Volume features.
*/
@Delegate
Optional<? extends VolumeAsyncApi> getVolumeExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Volume features.
*/
@Delegate
Optional<? extends VolumeAttachmentAsyncApi> getVolumeAttachmentExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Volume Type features.
*/
@Delegate
Optional<? extends VolumeTypeAsyncApi> getVolumeTypeExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Volume Type features.
*/
@Delegate
Optional<? extends ConsolesAsyncApi> getConsolesExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
}

View File

@ -15,10 +15,8 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jclouds.openstack.nova.v2_0.config; package org.jclouds.openstack.nova.v2_0.config;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI; import java.net.URI;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -30,101 +28,30 @@ import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import org.jclouds.openstack.nova.v2_0.NovaApi; import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.openstack.nova.v2_0.NovaAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneApi;
import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.ConsolesApi;
import org.jclouds.openstack.nova.v2_0.extensions.ConsolesAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces; import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces;
import org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsApi;
import org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.HostAdministrationApi;
import org.jclouds.openstack.nova.v2_0.extensions.HostAdministrationAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.HostAggregateApi;
import org.jclouds.openstack.nova.v2_0.extensions.HostAggregateAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.KeyPairApi;
import org.jclouds.openstack.nova.v2_0.extensions.KeyPairAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.QuotaApi;
import org.jclouds.openstack.nova.v2_0.extensions.QuotaAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupApi;
import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.ServerAdminApi;
import org.jclouds.openstack.nova.v2_0.extensions.ServerAdminAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.ServerWithSecurityGroupsApi;
import org.jclouds.openstack.nova.v2_0.extensions.ServerWithSecurityGroupsAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.SimpleTenantUsageApi;
import org.jclouds.openstack.nova.v2_0.extensions.SimpleTenantUsageAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.VirtualInterfaceApi;
import org.jclouds.openstack.nova.v2_0.extensions.VirtualInterfaceAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.VolumeApi;
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAttachmentApi;
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAttachmentAsyncApi;
import org.jclouds.openstack.nova.v2_0.extensions.VolumeTypeApi;
import org.jclouds.openstack.nova.v2_0.extensions.VolumeTypeAsyncApi;
import org.jclouds.openstack.nova.v2_0.features.FlavorApi;
import org.jclouds.openstack.nova.v2_0.features.FlavorAsyncApi;
import org.jclouds.openstack.nova.v2_0.features.ImageApi;
import org.jclouds.openstack.nova.v2_0.features.ImageAsyncApi;
import org.jclouds.openstack.nova.v2_0.features.ServerApi;
import org.jclouds.openstack.nova.v2_0.features.ServerAsyncApi;
import org.jclouds.openstack.nova.v2_0.handlers.NovaErrorHandler; import org.jclouds.openstack.nova.v2_0.handlers.NovaErrorHandler;
import org.jclouds.openstack.v2_0.domain.Extension; import org.jclouds.openstack.v2_0.domain.Extension;
import org.jclouds.openstack.v2_0.features.ExtensionApi;
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet; import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.HttpApiModule;
import org.jclouds.rest.functions.ImplicitOptionalConverter; import org.jclouds.rest.functions.ImplicitOptionalConverter;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
* Configures the Nova connection. * Configures the Nova connection.
*
*/ */
@ConfiguresRestClient @ConfiguresRestClient
public class NovaRestClientModule<S extends NovaApi, A extends NovaAsyncApi> extends RestClientModule<S, A> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder() public class NovaHttpApiModule extends HttpApiModule<NovaApi> {
.put(ServerApi.class, ServerAsyncApi.class)
.put(FlavorApi.class, FlavorAsyncApi.class)
.put(ImageApi.class, ImageAsyncApi.class)
.put(ExtensionApi.class, ExtensionAsyncApi.class)
.put(FloatingIPApi.class, FloatingIPAsyncApi.class)
.put(AvailabilityZoneApi.class, AvailabilityZoneAsyncApi.class)
.put(SecurityGroupApi.class, SecurityGroupAsyncApi.class)
.put(KeyPairApi.class, KeyPairAsyncApi.class)
.put(HostAdministrationApi.class, HostAdministrationAsyncApi.class)
.put(SimpleTenantUsageApi.class, SimpleTenantUsageAsyncApi.class)
.put(VirtualInterfaceApi.class, VirtualInterfaceAsyncApi.class)
.put(ServerWithSecurityGroupsApi.class, ServerWithSecurityGroupsAsyncApi.class)
.put(ServerAdminApi.class, ServerAdminAsyncApi.class)
.put(HostAggregateApi.class, HostAggregateAsyncApi.class)
.put(FlavorExtraSpecsApi.class, FlavorExtraSpecsAsyncApi.class)
.put(QuotaApi.class, QuotaAsyncApi.class)
.put(VolumeApi.class, VolumeAsyncApi.class)
.put(VolumeAttachmentApi.class, VolumeAttachmentAsyncApi.class)
.put(VolumeTypeApi.class, VolumeTypeAsyncApi.class)
.put(ConsolesApi.class, ConsolesAsyncApi.class)
.build();
@SuppressWarnings("unchecked") public NovaHttpApiModule() {
public NovaRestClientModule() {
super(TypeToken.class.cast(typeToken(NovaApi.class)), TypeToken.class.cast(typeToken(NovaAsyncApi.class)), DELEGATE_MAP);
}
protected NovaRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType,
Map<Class<?>, Class<?>> sync2Async) {
super(syncClientType, asyncClientType, sync2Async);
} }
@Override @Override

View File

@ -16,19 +16,39 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import com.google.common.annotations.Beta; import javax.inject.Named;
import com.google.common.collect.FluentIterable; import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.AvailabilityZone; import org.jclouds.openstack.nova.v2_0.domain.zonescoped.AvailabilityZone;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
/**
* Provides access to the OpenStack Compute (Nova) Availability Zone Extension API.
*/
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AVAILABILITY_ZONE) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AVAILABILITY_ZONE)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-availability-zone")
public interface AvailabilityZoneApi { public interface AvailabilityZoneApi {
/** /**
* @return all availability zones * @return all availability zones
*/ */
FluentIterable<? extends AvailabilityZone> list(); @Named("availabilityZone:list")
@GET
@SelectJson("availabilityZoneInfo")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<AvailabilityZone> list();
} }

View File

@ -1,52 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.Fallbacks;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.zonescoped.AvailabilityZone;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AVAILABILITY_ZONE)
@RequestFilters(AuthenticateRequest.class)
public interface AvailabilityZoneAsyncApi {
/**
* @return all availability zones
*/
@GET
@Path("/os-availability-zone")
@SelectJson("availabilityZoneInfo")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(Fallbacks.EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends AvailabilityZone>> list();
}

View File

@ -16,26 +16,51 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindConsoleToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.Console; import org.jclouds.openstack.nova.v2_0.domain.Console;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
/** /**
* Provides synchronous access to Consoles. * Provides access to the OpenStack Compute (Nova) Consoles Extension API.
* <p/> * <p/>
* *
* @see ConsoleAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CONSOLES) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CONSOLES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface ConsolesApi { public interface ConsolesApi {
/** /**
* Get the Console * Gets the specified server Console.
*
* @param serverId Server id * @param serverId Server id
* @param type see {@link Console.Type} * @param type see {@link Console.Type}
* @return a Console object containing the console url and type. * @return a Console object containing the console url and type.
*/ */
Console getConsole(String serverId, Console.Type type); @Named("consoles:getConsole")
@POST
@Path("/servers/{serverId}/action")
@SelectJson("console")
@Produces(MediaType.APPLICATION_JSON)
@Fallback(MapHttp4xxCodesToExceptions.class)
@MapBinder(BindConsoleToJsonPayload.class)
Console getConsole(@PathParam("serverId") String serverId, @PayloadParam("type") Console.Type type);
} }

View File

@ -1,68 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.Console;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.nova.v2_0.binders.BindConsoleToJsonPayload;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Consoles via the REST API.
* <p/>
*
* @see ConsoleApi
* @see ExtensionAsyncApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CONSOLES)
@RequestFilters(AuthenticateRequest.class)
public interface ConsolesAsyncApi {
/**
* @see ConsolesApi#getConsole
*/
@Named("server:console")
@POST
@Path("/servers/{serverId}/action")
@SelectJson("console")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Fallback(MapHttp4xxCodesToExceptions.class)
@MapBinder(BindConsoleToJsonPayload.class)
ListenableFuture<? extends Console> getConsole(@PathParam("serverId") String serverId,
@PayloadParam("type") Console.Type type);
}

View File

@ -17,28 +17,58 @@
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import java.util.Map; import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
/** /**
* Provide access to extra metadata for Nova flavors. * Provides access to the OpenStack Compute (Nova) Flavor Extra Specs Extension API.
* *
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.flavorextraspecs.html"/>
* @see org.jclouds.openstack.nova.v2_0.features.FlavorApi * @see org.jclouds.openstack.nova.v2_0.features.FlavorApi
* @see org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLAVOR_EXTRA_SPECS) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLAVOR_EXTRA_SPECS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors")
public interface FlavorExtraSpecsApi { public interface FlavorExtraSpecsApi {
/** /**
* Retrieve all extra specs for a flavor * Retrieves all extra specs for a flavor
* *
* @return the set of extra metadata for the flavor * @return the set of extra metadata for the flavor
*/ */
Map<String, String> getMetadata(String flavorId); @Named("flavorExtraSpecs:getMetadata")
@GET
@Path("/{id}/os-extra_specs")
@SelectJson("extra_specs")
@Fallback(EmptyMapOnNotFoundOr404.class)
Map<String, String> getMetadata(@PathParam("id") String flavorId);
/** /**
* Creates or updates the extra specs for a given flavor * Creates or updates the extra specs for a given flavor
@ -46,31 +76,55 @@ public interface FlavorExtraSpecsApi {
* @param flavorId the id of the flavor to modify * @param flavorId the id of the flavor to modify
* @param specs the extra specs to apply * @param specs the extra specs to apply
*/ */
Boolean updateMetadata(String flavorId, Map<String, String> specs); @Named("flavorExtraSpecs:updateMetadata")
@POST
@Path("/{id}/os-extra_specs")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindToJsonPayload.class)
@Fallback(FalseOnNotFoundOr404.class)
Boolean updateMetadata(@PathParam("id") String flavorId,
@PayloadParam("extra_specs") Map<String, String> specs);
/** /**
* Return a single extra spec value * Return a single extra spec value
* *
* @param flavorId the id of the flavor to modify * @param id the id of the flavor to modify
* @param key the extra spec key to retrieve * @param key the extra spec key to retrieve
*/ */
String getMetadataKey(String flavorId, String key); @Named("flavorExtraSpecs:getMetadataKey")
@GET
@Path("/{id}/os-extra_specs/{key}")
@Unwrap
@Fallback(NullOnNotFoundOr404.class)
@Nullable
String getMetadataKey(@PathParam("id") String flavorId, @PathParam("key") String key);
/** /**
* Creates or updates a single extra spec value * Creates or updates a single extra spec value
* *
* @param flavorId the id of the flavor to modify * @param id the id of the flavor to modify
* @param key the extra spec key (when creating ensure this does not include whitespace or other difficult characters) * @param key the extra spec key (when creating ensure this does not include whitespace or
* other difficult characters)
* @param value the value to associate with the key * @param value the value to associate with the key
*/ */
Boolean updateMetadataEntry(String flavorId, String key, String value); @Named("flavorExtraSpecs:updateMetadataEntry")
@PUT
@Path("/{id}/os-extra_specs/{key}")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"{key}\":\"{value}\"%7D")
@Fallback(FalseOnNotFoundOr404.class)
Boolean updateMetadataEntry(@PathParam("id") String flavorId,
@PathParam("key") @PayloadParam("key") String key, @PayloadParam("value") String value);
/** /**
* Deletes an extra spec * Deletes an extra spec
* *
* @param flavorId the id of the flavor to modify * @param id the id of the flavor to modify
* @param key the extra spec key to delete * @param key the extra spec key to delete
*/ */
Boolean deleteMetadataKey(String flavorId, String key); @Named("flavorExtraSpecs:deleteMetadataKey")
@DELETE
@Path("/{id}/os-extra_specs/{key}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean deleteMetadataKey(@PathParam("id") String flavorId, @PathParam("key") String key);
} }

View File

@ -1,117 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provide access to extra metadata for Nova flavors.
*
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.flavorextraspecs.html"/>
* @see org.jclouds.openstack.nova.v2_0.features.FlavorApi
* @see FlavorExtraSpecsApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLAVOR_EXTRA_SPECS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface FlavorExtraSpecsAsyncApi {
/**
* @see FlavorExtraSpecsApi#getMetadata(String)
*/
@Named("flavor:getmetadata")
@GET
@SelectJson("extra_specs")
@Path("/flavors/{flavor_id}/os-extra_specs")
@Fallback(EmptyMapOnNotFoundOr404.class)
ListenableFuture<Map<String, String>> getMetadata(@PathParam("flavor_id") String flavorId);
/**
* @see FlavorExtraSpecsApi#updateMetadataEntry(String, String, String)
*/
@Named("flavor:updatemetadata")
@POST
@Path("/flavors/{flavor_id}/os-extra_specs")
@Produces(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
@MapBinder(BindToJsonPayload.class)
ListenableFuture<Boolean> updateMetadata(@PathParam("flavor_id") String flavorId, @PayloadParam("extra_specs") Map<String, String> specs);
/**
* @see FlavorExtraSpecsApi#getMetadataKey(String, String)
*/
@Named("flavor:getmetadata")
@GET
@Path("/flavors/{flavor_id}/os-extra_specs/{key}")
@Unwrap
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<String> getMetadataKey(@PathParam("flavor_id") String flavorId, @PathParam("key") String key);
/**
* @see FlavorExtraSpecsApi#updateMetadataEntry(String, String, String)
*/
@Named("flavor:updatemetadata")
@PUT
@Path("/flavors/{flavor_id}/os-extra_specs/{key}")
@Produces(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
@Payload("%7B\"{key}\":\"{value}\"%7D")
ListenableFuture<Boolean> updateMetadataEntry(@PathParam("flavor_id") String flavorId,
@PathParam("key") @PayloadParam("key") String key,
@PayloadParam("value") String value);
/**
* @see FlavorExtraSpecsApi#deleteMetadataKey(String, String)
*/
@Named("flavor:deletemetadata")
@DELETE
@Path("/flavors/{flavor_id}/os-extra_specs/{key}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> deleteMetadataKey(@PathParam("flavor_id") String flavorId,
@PathParam("key") String key);
}

View File

@ -16,82 +16,139 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.FloatingIP; import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides synchronous access to Floating IPs. * Provides access to the OpenStack Compute (Nova) Floating IP extension API.
* <p/>
*
* @see FloatingIPAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface FloatingIPApi { public interface FloatingIPApi {
/** /**
* List all Floating IP addresses * Lists all Floating IP addresses
* *
* @return all Floating IPs * @return all Floating IPs
*/ */
FluentIterable<? extends FloatingIP> list(); @Named("floatingIP:list")
@GET
@Path("/os-floating-ips")
@SelectJson("floating_ips")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<FloatingIP> list();
/** /**
* Get a specific Floating IP address * Gets a specific Floating IP address
* *
* @return all Floating IPs * @return all Floating IPs
*/ */
FloatingIP get(String id); @Named("floatingIP:get")
@GET
@Path("/os-floating-ips/{id}")
@SelectJson("floating_ip")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
FloatingIP get(@PathParam("id") String id);
/** /**
* Allocate a Floating IP address * Allocates a Floating IP address
* *
* @return a newly created FloatingIP * @return a newly created FloatingIP
*/ */
@Named("floatingIP:create")
@POST
@Path("/os-floating-ips")
@SelectJson("floating_ip")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{}")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
FloatingIP create(); FloatingIP create();
/** /**
* Allocate a Floating IP address from a pool * Allocates a Floating IP address from a pool
* *
* @param pool * @param pool
* Pool to allocate IP address from * Pool to allocate IP address from
* @return a newly created FloatingIP * @return a newly created FloatingIP
*/ */
FloatingIP allocateFromPool(String pool); @Named("floatingIP:allocateFromPool")
@POST
@Path("/os-floating-ips")
@SelectJson("floating_ip")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"pool\":\"{pool}\"%7D")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
FloatingIP allocateFromPool(@PayloadParam("pool") String pool);
/** /**
* Decreate a Floating IP address * Deletes a Floating IP address
* *
* @param id * @param id
* the Floating IP id * the Floating IP id
*/ */
void delete(String id); @Named("floatingIP:delete")
@DELETE
@Path("/os-floating-ips/{id}")
void delete(@PathParam("id") String id);
/** /**
* Add a Floating IP address to a Server * Adds a Floating IP address to a Server
* *
* @param serverId * @param id
* the serverId * the server id
* @param address * @param address
* the IP address to add * the IP address to add
* *
* NOTE: Possibly move this to ServerApi? * NOTE: Possibly move this to ServerApi?
*/ */
void addToServer(String address, String serverId); @Named("floatingIP:add")
@POST
@Path("/servers/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"addFloatingIp\":%7B\"address\":\"{address}\"%7D%7D")
void addToServer(@PayloadParam("address") String address, @PathParam("id") String serverId);
/** /**
* Remove a Floating IP address from a Server * Removes a Floating IP address from a Server
* *
* @param serverId * @param id
* the serverId * the server id
* @param address * @param address
* the IP address to remove * the IP address to remove
* *
* NOTE: Possibly move this to ServerApi? * NOTE: Possibly move this to ServerApi?
*/ */
void removeFromServer(String address, String serverId); @Named("floatingIP:remove")
@POST
@Path("/servers/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"removeFloatingIp\":%7B\"address\":\"{address}\"%7D%7D")
void removeFromServer(@PayloadParam("address") String address, @PathParam("id") String serverId);
} }

View File

@ -1,144 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Floating IPs via the REST API.
* <p/>
*
* @see FloatingIPApi
* @see ExtensionAsyncApi
* @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://wiki.openstack.org/os_api_floating_ip"/>
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS)
@RequestFilters(AuthenticateRequest.class)
public interface FloatingIPAsyncApi {
/**
* @see FloatingIPApi#list
*/
@Named("floatingip:list")
@GET
@Path("/os-floating-ips")
@SelectJson("floating_ips")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends FloatingIP>> list();
/**
* @see FloatingIPApi#get
*/
@Named("floatingip:get")
@GET
@Path("/os-floating-ips/{id}")
@SelectJson("floating_ip")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends FloatingIP> get(@PathParam("id") String id);
/**
* @see FloatingIPApi#create
*/
@Named("floatingip:create")
@POST
@Path("/os-floating-ips")
@SelectJson("floating_ip")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Payload("{}")
ListenableFuture<? extends FloatingIP> create();
/**
* @see org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi#allocateFromPool
*/
@Named("floatingip:create")
@POST
@Path("/os-floating-ips")
@SelectJson("floating_ip")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Payload("%7B\"pool\":\"{pool}\"%7D")
ListenableFuture<? extends FloatingIP> allocateFromPool(@PayloadParam("pool") String pool);
/**
* @see FloatingIPApi#delete
*/
@Named("floatingip:delete")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Path("/os-floating-ips/{id}")
ListenableFuture<Void> delete(@PathParam("id") String id);
/**
* @see FloatingIPApi#addToServer
*/
@Named("floatingip:add")
@POST
@Path("/servers/{server}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"addFloatingIp\":%7B\"address\":\"{address}\"%7D%7D")
ListenableFuture<Void> addToServer(@PayloadParam("address") String address,
@PathParam("server") String serverId);
/**
* @see FloatingIPApi#removeFromServer
*/
@Named("floatingip:remove")
@POST
@Path("/servers/{server}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"removeFloatingIp\":%7B\"address\":\"{address}\"%7D%7D")
ListenableFuture<Void> removeFromServer(@PayloadParam("address") String address,
@PathParam("server") String serverId);
}

View File

@ -16,51 +16,94 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.Host; import org.jclouds.openstack.nova.v2_0.domain.Host;
import org.jclouds.openstack.nova.v2_0.domain.HostResourceUsage; import org.jclouds.openstack.nova.v2_0.domain.HostResourceUsage;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.MaintenanceModeDisabledResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.MaintenanceModeEnabledResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.PowerIsRebootResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.PowerIsShutdownResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.PowerIsStartupResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.StatusDisabledResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.StatusEnabledResponseParser;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides asynchronous access to Host Administration features via the REST API. * Provides access to OpenStack Compute (Nova) Host Administration extension API.
* <p/>
*
* @see HostAdministrationAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.HOSTS) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.HOSTS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-hosts")
public interface HostAdministrationApi { public interface HostAdministrationApi {
/** /**
* Returns the list of hosts * Returns the list of hosts
* *
* @return the usage information * @return the usage information
*/ */
FluentIterable<? extends Host> list(); @Named("hostAdmin:list")
@GET
@SelectJson("hosts")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<Host> list();
/** /**
* 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
*/ */
FluentIterable<? extends HostResourceUsage> listResourceUsage(String hostId); @Named("hostAdmin:listResourceUsage")
@GET
@Path("/{id}")
@SelectJson("host")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<HostResourceUsage> listResourceUsage(@PathParam("id") String hostId);
/** /**
* Allow the specified host to accept new instances. * Allow the specified host to accept new instances.
* *
* @return true if successful * @return true if successful
*/ */
boolean enable(String hostId); @Named("hostAdmin:enable")
@PUT
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"status\":\"enable\"}")
@ResponseParser(StatusEnabledResponseParser.class)
boolean enable(@PathParam("id") String hostId);
/** /**
* Prevent the specified host from accepting new instances. * Prevent the specified host from accepting new instances.
* *
* @return true if successful * @return true if successful
*/ */
boolean disable(String hostId); @Named("hostAdmin:disable")
@PUT
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"status\":\"disable\"}")
@ResponseParser(StatusDisabledResponseParser.class)
boolean disable(@PathParam("id") String hostId);
/** /**
* Start host maintenance window. * Start host maintenance window.
@ -69,34 +112,57 @@ public interface HostAdministrationApi {
* *
* @return true if successful * @return true if successful
*/ */
boolean startMaintenance(String hostId); @Named("hostAdmin:startMaintenance")
@PUT
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"maintenance_mode\":\"enable\"}")
@ResponseParser(MaintenanceModeEnabledResponseParser.class)
boolean startMaintenance(@PathParam("id") String hostId);
/** /**
* Stop host maintenance window. * Stop host maintenance window.
* *
* @return true if successful * @return true if successful
*/ */
boolean stopMaintenance(String hostId); @Named("hostAdmin:stopMaintenance")
@PUT
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"maintenance_mode\":\"disable\"}")
@ResponseParser(MaintenanceModeDisabledResponseParser.class)
boolean stopMaintenance(@PathParam("id") String hostId);
/** /**
* Startup a host. * Startup a host.
* *
* @return true if successful * @return true if successful
*/ */
boolean startup(String hostId); @Named("hostAdmin:startup")
@GET
@Path("/{id}/startup")
@ResponseParser(PowerIsStartupResponseParser.class)
boolean startup(@PathParam("id") String hostId);
/** /**
* Shutdown a host. * Shutdown a host.
* *
* @return true if successful * @return true if successful
*/ */
boolean shutdown(String hostId); @Named("hostAdmin:shutdown")
@GET
@Path("/{id}/shutdown")
@ResponseParser(PowerIsShutdownResponseParser.class)
boolean shutdown(@PathParam("id") String hostId);
/** /**
* Reboot a host. * Reboot a host.
* *
* @return true if successful * @return true if successful
*/ */
boolean reboot(String hostId); @Named("hostAdmin:reboot")
@GET
@Path("/{id}/reboot")
@ResponseParser(PowerIsRebootResponseParser.class)
boolean reboot(@PathParam("id") String hostId);
} }

View File

@ -1,156 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.Host;
import org.jclouds.openstack.nova.v2_0.domain.HostResourceUsage;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.MaintenanceModeDisabledResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.MaintenanceModeEnabledResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.PowerIsRebootResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.PowerIsShutdownResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.PowerIsStartupResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.StatusDisabledResponseParser;
import org.jclouds.openstack.nova.v2_0.functions.FieldValueResponseParsers.StatusEnabledResponseParser;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Host Administration features via the REST API.
* <p/>
*
* @see HostAdministrationApi
* @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/nova.api.openstack.compute.contrib.hosts.html" />
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.HOSTS)
@RequestFilters(AuthenticateRequest.class)
@Path("/os-hosts")
@Consumes(MediaType.APPLICATION_JSON)
public interface HostAdministrationAsyncApi {
/**
* @see HostAdministrationApi#list()
*/
@Named("hostadmin:list")
@GET
@SelectJson("hosts")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends Host>> list();
/**
* @see HostAdministrationApi#listResourceUsage(String)
*/
@Named("hostadmin:listresource")
@GET
@Path("/{id}")
@SelectJson("host")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends HostResourceUsage>> listResourceUsage(@PathParam("id") String hostId);
/**
* @see HostAdministrationApi#enable(String)
*/
@Named("hostadmin:enable")
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}")
@Payload("{\"status\":\"enable\"}")
@ResponseParser(StatusEnabledResponseParser.class)
ListenableFuture<Boolean> enable(@PathParam("id") String hostId);
/**
* @see HostAdministrationApi#disable(String)
*/
@Named("hostadmin:disable")
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}")
@Payload("{\"status\":\"disable\"}")
@ResponseParser(StatusDisabledResponseParser.class)
ListenableFuture<Boolean> disable(@PathParam("id") String hostId);
/**
* @see HostAdministrationApi#startMaintenance(String)
*/
@Named("hostadmin:startmaintenance")
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}")
@Payload("{\"maintenance_mode\":\"enable\"}")
@ResponseParser(MaintenanceModeEnabledResponseParser.class)
ListenableFuture<Boolean> startMaintenance(@PathParam("id") String hostId);
/**
* @see HostAdministrationApi#stopMaintenance(String)
*/
@Named("hostadmin:stopmaintenance")
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}")
@Payload("{\"maintenance_mode\":\"disable\"}")
@ResponseParser(MaintenanceModeDisabledResponseParser.class)
ListenableFuture<Boolean> stopMaintenance(@PathParam("id") String hostId);
/**
* @see HostAdministrationApi#startup(String)
*/
@Named("hostadmin:startup")
@GET
@Path("/{id}/startup")
@ResponseParser(PowerIsStartupResponseParser.class)
ListenableFuture<Boolean> startup(@PathParam("id") String hostId);
/**
* @see HostAdministrationApi#shutdown(String)
*/
@Named("hostadmin:shutdown")
@GET
@Path("/{id}/shutdown")
@ResponseParser(PowerIsShutdownResponseParser.class)
ListenableFuture<Boolean> shutdown(@PathParam("id") String hostId);
/**
* @see HostAdministrationApi#reboot(String)
*/
@Named("hostadmin:reboot")
@GET
@Path("/{id}/reboot")
@ResponseParser(PowerIsRebootResponseParser.class)
ListenableFuture<Boolean> reboot(@PathParam("id") String hostId);
}

View File

@ -17,70 +17,141 @@
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import java.util.Map; import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.HostAggregate; import org.jclouds.openstack.nova.v2_0.domain.HostAggregate;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provide access to Host Aggregates in Nova (alias "OS-AGGREGATES") * Provide access to the OpenStack Compute (Nova) Host Aggregates extension API.
*
* @see HostAggregateAsyncApi
* @see <a href="http://nova.openstack.org/api_ext/ext_aggregates.html"/>
* @see <a href="http://wiki.openstack.org/host-aggregates"/>
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AGGREGATES) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AGGREGATES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-aggregates")
public interface HostAggregateApi { public interface HostAggregateApi {
/** /**
* Lists all host aggregates.
*
* @return the set of host aggregates. * @return the set of host aggregates.
*/ */
FluentIterable<? extends HostAggregate> list(); @Named("hostAggregate:list")
@GET
@SelectJson("aggregates")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<HostAggregate> list();
/** /**
* Retrieves the details of an aggregate, hosts and metadata included. * Retrieves the details of an aggregate, hosts and metadata included.
* *
* @return the details of the aggregate requested. * @return the details of the aggregate requested.
*/ */
HostAggregate get(String id); @Named("hostAggregate:get")
@GET
@Path("/{id}")
@SelectJson("aggregate")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
HostAggregate get(@PathParam("id") String id);
/** /**
* Creates an aggregate, given its name and availability zone. * Creates an aggregate, given its name and availability zone.
* *
* @return the newly created Aggregate * @return the newly created Aggregate
*/ */
HostAggregate createInAvailabilityZone(String name, String availabilityZone); @Named("hostAggregate:create")
@POST
@SelectJson("aggregate")
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("aggregate")
HostAggregate createInAvailabilityZone(@PayloadParam("name") String name,
@PayloadParam("availability_zone") String availabilityZone);
/** /**
* Updates the name of an aggregate. * Updates the name of an aggregate.
*/ */
HostAggregate updateName(String id, String name); @Named("hostAggregate:update")
@POST
@Path("/{id}")
@SelectJson("aggregate")
@WrapWith("aggregate")
HostAggregate updateName(@PathParam("id") String id, @PayloadParam("name") String name);
/** /**
* Updates the availability zone an aggregate. * Updates the availability zone for an aggregate.
*/ */
HostAggregate updateAvailabilityZone(String id, String availabilityZone); @Named("hostAggregate:update")
@POST
@Path("/{id}")
@SelectJson("aggregate")
@WrapWith("aggregate")
HostAggregate updateAvailabilityZone(@PathParam("id") String id,
@PayloadParam("availability_zone") String availabilityZone);
/** /**
* Removes an aggregate. * Removes an aggregate.
*/ */
Boolean delete(String id); @Named("hostAggregate:delete")
@DELETE
@Path("/{id}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean delete(@PathParam("id") String id);
/** /**
* Adds a host to an aggregate * Adds a host to an aggregate
*/ */
HostAggregate addHost(String id, String host); @Named("hostAggregate:addHost")
@POST
@Path("/{id}/action")
@SelectJson("aggregate")
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("add_host")
HostAggregate addHost(@PathParam("id") String id, @PayloadParam("host") String host);
/** /**
* Removes a host from an aggregate * Removes a host from an aggregate
*/ */
HostAggregate removeHost(String id, String host); @Named("hostAggregate:removeHost")
@POST
@Path("/{id}/action")
@SelectJson("aggregate")
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("remove_host")
HostAggregate removeHost(@PathParam("id") String id, @PayloadParam("host") String host);
/** /**
* Adds metadata to an aggregate * Adds metadata to an aggregate
*/ */
HostAggregate setMetadata(String id, Map<String, String> metadata); @Named("hostAggregate:setMetadata")
@POST
@Path("/{id}/action")
@SelectJson("aggregate")
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("set_metadata")
HostAggregate setMetadata(@PathParam("id") String id,
@PayloadParam("metadata") Map<String, String> metadata);
} }

View File

@ -1,160 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.HostAggregate;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provide access to Aggregates in Nova.
*
* @see HostAggregateApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AGGREGATES)
@RequestFilters(AuthenticateRequest.class)
@Path("/os-aggregates")
public interface HostAggregateAsyncApi {
/**
* @see HostAggregateApi#list()
*/
@Named("hostaggregate:list")
@GET
@SelectJson("aggregates")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends HostAggregate>> list();
/**
* @see HostAggregateApi#get(String)
*/
@Named("hostaggregate:get")
@GET
@Path("/{id}")
@SelectJson("aggregate")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends HostAggregate> get(@PathParam("id") String id);
/**
* @see HostAggregateApi#createInAvailabilityZone(String, String)
*/
@Named("hostaggregate:create")
@POST
@SelectJson("aggregate")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("aggregate")
ListenableFuture<? extends HostAggregate> createInAvailabilityZone(@PayloadParam("name") String name,
@PayloadParam("availability_zone") String availabilityZone);
/**
* @see HostAggregateApi#updateName
*/
@Named("hostaggregate:update")
@POST
@Path("/{id}")
@SelectJson("aggregate")
@Consumes(MediaType.APPLICATION_JSON)
@WrapWith("aggregate")
ListenableFuture<? extends HostAggregate> updateName(@PathParam("id") String id, @PayloadParam("name") String name);
/**
* @see HostAggregateApi#updateAvailabilityZone
*/
@Named("hostaggregate:update")
@POST
@Path("/{id}")
@SelectJson("aggregate")
@Consumes(MediaType.APPLICATION_JSON)
@WrapWith("aggregate")
ListenableFuture<? extends HostAggregate> updateAvailabilityZone(@PathParam("id") String id, @PayloadParam("availability_zone") String availabilityZone);
/**
* @see HostAggregateApi#delete(String)
*/
@Named("hostaggregate:delete")
@DELETE
@Path("/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> delete(@PathParam("id") String id);
/**
* @see HostAggregateApi#addHost(String,String)
*/
@Named("hostaggregate:addhost")
@POST
@Path("/{id}/action")
@SelectJson("aggregate")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("add_host")
ListenableFuture<? extends HostAggregate> addHost(@PathParam("id") String id, @PayloadParam("host") String host);
/**
* @see HostAggregateApi#removeHost(String,String)
*/
@Named("hostaggregate:removehost")
@POST
@Path("/{id}/action")
@SelectJson("aggregate")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("remove_host")
ListenableFuture<? extends HostAggregate> removeHost(@PathParam("id") String id, @PayloadParam("host") String host);
/**
* @see HostAggregateApi#setMetadata
*/
@Named("hostaggregate:setmetadata")
@POST
@Path("/{id}/action")
@SelectJson("aggregate")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("set_metadata")
ListenableFuture<? extends HostAggregate> setMetadata(@PathParam("id") String id, @PayloadParam("metadata") Map<String, String> metadata);
}

View File

@ -16,28 +16,55 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindKeyPairToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.KeyPair; import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseKeyPairs;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides synchronous access to the OpenStack Nova Key Pair Extension API. * Provides access to the OpenStack Compute (Nova) Key Pair Extension API.
* <p/>
*
* @see KeyPairAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-keypairs")
public interface KeyPairApi { public interface KeyPairApi {
/** /**
* Lists all Key Pairs. * Lists all Key Pairs.
* *
* @return all Key Pairs * @return all Key Pairs
*/ */
@Named("keypair:list")
@GET
@ResponseParser(ParseKeyPairs.class)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<KeyPair> list(); FluentIterable<KeyPair> list();
/** /**
@ -45,7 +72,12 @@ public interface KeyPairApi {
* *
* @return the created {@link KeyPair}. * @return the created {@link KeyPair}.
*/ */
KeyPair create(String name); @Named("keypair:create")
@POST
@SelectJson("keypair")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"keypair\":%7B\"name\":\"{name}\"%7D%7D")
KeyPair create(@PayloadParam("name") String name);
/** /**
@ -53,7 +85,13 @@ public interface KeyPairApi {
* *
* @return the created {@link KeyPair}. * @return the created {@link KeyPair}.
*/ */
KeyPair createWithPublicKey(String name, String publicKey); @Named("keypair:create")
@POST
@SelectJson("keypair")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindKeyPairToJsonPayload.class)
KeyPair createWithPublicKey(@PayloadParam("name") String name,
@PayloadParam("public_key") String publicKey);
/** /**
* Gets a specific {@link KeyPair} by name. * Gets a specific {@link KeyPair} by name.
@ -63,7 +101,14 @@ public interface KeyPairApi {
* *
* @return the specified {@link KeyPair}, otherwise null. * @return the specified {@link KeyPair}, otherwise null.
*/ */
KeyPair get(String name); @Named("keypair:get")
@GET
@Path("/{name}")
@SelectJson("keypair")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
KeyPair get(@PathParam("name") String name);
/** /**
* Deletes a {@link KeyPair}. * Deletes a {@link KeyPair}.
@ -73,6 +118,9 @@ public interface KeyPairApi {
* *
* @return {@code true} if the {@link KeyPair} was deleted, otherwise {@code false}. * @return {@code true} if the {@link KeyPair} was deleted, otherwise {@code false}.
*/ */
boolean delete(String name); @Named("keypair:delete")
@DELETE
@Path("/{name}")
@Fallback(FalseOnNotFoundOr404.class)
boolean delete(@PathParam("name") String name);
} }

View File

@ -1,105 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindKeyPairToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseKeyPairs;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to the OpenStack Nova Key Pair Extension API.
* <p/>
*
* @see KeyPairApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
@RequestFilters(AuthenticateRequest.class)
public interface KeyPairAsyncApi {
@Named("keypair:list")
@GET
@Path("/os-keypairs")
@ResponseParser(ParseKeyPairs.class)
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<FluentIterable<KeyPair>> list();
@Named("keypair:create")
@POST
@Path("/os-keypairs")
@SelectJson("keypair")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"keypair\":%7B\"name\":\"{name}\"%7D%7D")
ListenableFuture<KeyPair> create(@PayloadParam("name") String name);
@Named("keypair:get")
@GET
@Path("/os-keypairs/{name}")
@SelectJson("keypair")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
ListenableFuture<KeyPair> get(@PathParam("name") String name);
@Named("keypair:create")
@POST
@Path("/os-keypairs")
@SelectJson("keypair")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindKeyPairToJsonPayload.class)
ListenableFuture<KeyPair> createWithPublicKey(@PayloadParam("name") String name,
@PayloadParam("public_key") String publicKey);
@Named("keypair:delete")
@DELETE
@Path("/os-keypairs/{name}")
@Fallback(FalseOnNotFoundOr404.class)
@Consumes
ListenableFuture<Boolean> delete(@PathParam("name") String name);
}

View File

@ -16,41 +16,78 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.Quota; import org.jclouds.openstack.nova.v2_0.domain.Quota;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
/** /**
* Provide access to OpenStack Compute (Nova) Quota Extension API.
* <p/>
* The quotas extension enables limiters placed on the resources used per tenant (project) for virtual instances. It is * The quotas extension enables limiters placed on the resources used per tenant (project) for virtual instances. It is
* used with the OpenStack Compute API 1.1 for administrators who need to control the amount of volumes, memory, floating * used with the OpenStack Compute API 1.1 for administrators who need to control the amount of volumes, memory, floating
* IP addresses, instances, or cores allowed within a defined tenant or project. * IP addresses, instances, or cores allowed within a defined tenant or project.
* <p/> * <p/>
* To use this extension, you need to have administrative rights to the tenants upon which you are placing quotas. * To use this extension, you need to have administrative rights to the tenants upon which you are placing quotas.
* *
* @see QuotaAsyncApi
* @see <a href="http://nova.openstack.org/api_ext/ext_quotas.html"/>
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.QUOTAS) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.QUOTAS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-quota-sets")
public interface QuotaApi { public interface QuotaApi {
/** /**
* @return the quota settings for the tenant * @return the quota settings for the tenant
*/ */
Quota getByTenant(String tenantId); @Named("quota:get")
@GET
@SelectJson("quota_set")
@Path("/{id}")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Quota getByTenant(@PathParam("id") String tenantId);
/** /**
* Update the quotas for a given tenant * Update the quotas for a given tenant
* *
* @return true if successful * @return true if successful
*/ */
boolean updateQuotaOfTenant(Quota quota, String tenantId); @Named("quota:update")
@PUT
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindToJsonPayload.class)
boolean updateQuotaOfTenant(@PayloadParam("quota_set") Quota quota,
@PathParam("id") String tenantId);
/** /**
* @return the set of default quotas for the tenant * @return the set of default quotas for the tenant
*/ */
Quota getDefaultsForTenant(String tenantId); @Named("quota:get")
@GET
@SelectJson("quota_set")
@Path("/{id}/defaults")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Quota getDefaultsForTenant(@PathParam("id") String tenantId);
} }

View File

@ -1,88 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.Quota;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provide access to Quota information for Nova tenants.
*
* @see QuotaApi
* @see <a href="http://nova.openstack.org/api_ext/ext_quotas.html"/>
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.QUOTAS)
@RequestFilters(AuthenticateRequest.class)
@Path("/os-quota-sets")
public interface QuotaAsyncApi {
/**
* @see QuotaApi#getDefaultsForTenant(String)
*/
@Named("quota:get")
@GET
@SelectJson("quota_set")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{tenant_id}")
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends Quota> getByTenant(@PathParam("tenant_id") String tenantId);
/**
* @see QuotaApi#updateQuotaOfTenant
*/
@Named("quota:update")
@PUT
@Path("/{tenant_id}")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindToJsonPayload.class)
ListenableFuture<Boolean> updateQuotaOfTenant(@PayloadParam("quota_set") Quota quota,
@PathParam("tenant_id") String tenantId);
/**
* @see QuotaApi#getDefaultsForTenant(String)
*/
@Named("quota:get")
@GET
@SelectJson("quota_set")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{tenant_id}/defaults")
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends Quota> getDefaultsForTenant(@PathParam("tenant_id") String tenantId);
}

View File

@ -16,73 +16,139 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindSecurityGroupRuleToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.Ingress; import org.jclouds.openstack.nova.v2_0.domain.Ingress;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup; import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule; import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides synchronous access to Security Groups. * Provides access to the OpenStack Compute (Nova) Security Group extension API.
* <p/>
*
* @see SecurityGroupAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SECURITY_GROUPS) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SECURITY_GROUPS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface SecurityGroupApi { public interface SecurityGroupApi {
/** /**
* List all Security Groups. * List all Security Groups.
* *
* @return all Security Groups * @return all Security Groups
*/ */
FluentIterable<? extends SecurityGroup> list(); @Named("securityGroup:list")
@GET
@Path("/os-security-groups")
@SelectJson("security_groups")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<SecurityGroup> list();
/** /**
* Get a specific Security Group * Get a specific Security Group
* *
* @return a specific Security Group * @return a specific Security Group
*/ */
SecurityGroup get(String id); @Named("securityGroup:get")
@GET
@Path("/os-security-groups/{id}")
@SelectJson("security_group")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
SecurityGroup get(@PathParam("id") String id);
/** /**
* Create a Security Group * Create a Security Group
* *
* @return a new Security Group * @return a new Security Group
*/ */
SecurityGroup createWithDescription(String name, String description); @Named("securityGroup:create")
@POST
@Path("/os-security-groups")
@SelectJson("security_group")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"security_group\":%7B\"name\":\"{name}\",\"description\":\"{description}\"%7D%7D")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
SecurityGroup createWithDescription(@PayloadParam("name") String name,
@PayloadParam("description") String description);
/** /**
* Delete a Security Group. * Delete a Security Group.
* *
* @return * @return
*/ */
boolean delete(String id); @Named("securityGroup:delete")
@DELETE
@Path("/os-security-groups/{id}")
@Fallback(FalseOnNotFoundOr404.class)
boolean delete(@PathParam("id") String id);
/** /**
* Create a Security Group Rule. * Create a Security Group Rule.
* *
* @return a new Security Group Rule * @return a new Security Group Rule
*/ */
SecurityGroupRule createRuleAllowingCidrBlock(String parentGroup, Ingress ingress, String sourceCidr); @Named("securityGroup:create")
@POST
@Path("/os-security-group-rules")
@SelectJson("security_group_rule")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindSecurityGroupRuleToJsonPayload.class)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
SecurityGroupRule createRuleAllowingCidrBlock(
@PayloadParam("parent_group_id") String parentGroup, Ingress ip_protocol,
@PayloadParam("cidr") String sourceCidr);
/** /**
* Create a Security Group Rule. * Create a Security Group Rule.
* *
* @return a new Security Group Rule * @return a new Security Group Rule
*/ */
SecurityGroupRule createRuleAllowingSecurityGroupId(String parentGroup, Ingress ingress, @Named("securityGroup:create")
String groupId); @POST
@Path("/os-security-group-rules")
@SelectJson("security_group_rule")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindSecurityGroupRuleToJsonPayload.class)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
SecurityGroupRule createRuleAllowingSecurityGroupId(
@PayloadParam("parent_group_id") String parentGroup, Ingress ip_protocol,
@PayloadParam("group_id") String groupId);
/** /**
* Delete a Security Group Rule. * Delete a Security Group Rule.
* *
* @return * @return
*/ */
Boolean deleteRule(String id); @Named("securityGroup:delete")
@DELETE
@Path("/os-security-group-rules/{id}")
@Fallback(FalseOnNotFoundOr404.class)
boolean deleteRule(@PathParam("id") String ruleId);
} }

View File

@ -1,151 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindSecurityGroupRuleToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.Ingress;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Security Groups via the REST API.
* <p/>
*
* @see SecurityGroupApi
* @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://wiki.openstack.org/os-security-groups" />
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SECURITY_GROUPS)
@RequestFilters(AuthenticateRequest.class)
public interface SecurityGroupAsyncApi {
/**
* @see SecurityGroupApi#list
*/
@Named("securitygroup:list")
@GET
@SelectJson("security_groups")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-security-groups")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends SecurityGroup>> list();
/**
* @see SecurityGroupApi#get
*/
@Named("securitygroup:get")
@GET
@Path("/os-security-groups/{id}")
@SelectJson("security_group")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends SecurityGroup> get(@PathParam("id") String id);
/**
* @see SecurityGroupApi#createWithDescription
*/
@Named("securitygroup:create")
@POST
@Path("/os-security-groups")
@SelectJson("security_group")
@Fallback(NullOnNotFoundOr404.class)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"security_group\":%7B\"name\":\"{name}\",\"description\":\"{description}\"%7D%7D")
ListenableFuture<? extends SecurityGroup> createWithDescription(@PayloadParam("name") String name,
@PayloadParam("description") String description);
/**
* @see SecurityGroupApi#delete
*/
@Named("securitygroup:delete")
@DELETE
@Path("/os-security-groups/{id}")
@Fallback(FalseOnNotFoundOr404.class)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Boolean> delete(@PathParam("id") String id);
/**
* @see SecurityGroupApi#createRuleAllowingCidrBlock
*/
@Named("securitygroup:create")
@POST
@Path("/os-security-group-rules")
@SelectJson("security_group_rule")
@Fallback(NullOnNotFoundOr404.class)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindSecurityGroupRuleToJsonPayload.class)
ListenableFuture<? extends SecurityGroupRule> createRuleAllowingCidrBlock(
@PayloadParam("parent_group_id") String parent_group_id, Ingress ip_protocol,
@PayloadParam("cidr") String cidr);
/**
* @see SecurityGroupApi#createRuleOnSecurityGroupToCidrBlock
*/
@Named("securitygroup:create")
@POST
@Path("/os-security-group-rules")
@SelectJson("security_group_rule")
@Fallback(NullOnNotFoundOr404.class)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindSecurityGroupRuleToJsonPayload.class)
ListenableFuture<? extends SecurityGroupRule> createRuleAllowingSecurityGroupId(
@PayloadParam("parent_group_id") String parent_group_id, Ingress ip_protocol,
@PayloadParam("group_id") String group_id);
/**
* @see SecurityGroupApi#deleteRule
*/
@Named("securitygroup:delete")
@DELETE
@Path("/os-security-group-rules/{security_group_rule_ID}")
@Fallback(FalseOnNotFoundOr404.class)
@Consumes
ListenableFuture<Boolean> deleteRule(@PathParam("security_group_rule_ID") String security_group_rule_ID);
}

View File

@ -16,65 +16,116 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.BackupType; import org.jclouds.openstack.nova.v2_0.domain.BackupType;
import org.jclouds.openstack.nova.v2_0.functions.ParseImageIdFromLocationHeader;
import org.jclouds.openstack.nova.v2_0.options.CreateBackupOfServerOptions; import org.jclouds.openstack.nova.v2_0.options.CreateBackupOfServerOptions;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
/** /**
* Provide access to the OpenStack Compute (Nova) Admin Server Actions Extension API.
*
* Provide additional actions for servers: * Provide additional actions for servers:
* 'suspend', 'resume', 'migrate', 'lock', 'unlock', 'resetNetwork', 'createBackup', 'pause', 'migrateLive', * 'suspend', 'resume', 'migrate', 'lock', 'unlock', 'resetNetwork', 'createBackup', 'pause', 'migrateLive',
* 'injectNetworkInfo', 'unpause' * 'injectNetworkInfo', 'unpause'
* *
* @see org.jclouds.openstack.nova.v2_0.extensions.ServerAdminAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.ADMIN_ACTIONS) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.ADMIN_ACTIONS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/{id}/action")
public interface ServerAdminApi { public interface ServerAdminApi {
/** /**
* Suspend a server. * Suspend a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean suspend(String id); @Named("serverAdmin:suspend")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"suspend\":null}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean suspend(@PathParam("id") String id);
/** /**
* Resume a server. * Resume a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean resume(String id); @Named("serverAdmin:resume")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"resume\":null}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean resume(@PathParam("id") String id);
/** /**
* Migrate a server. * Migrate a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean migrate(String id); @Named("serverAdmin:migrate")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"migrate\":null}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean migrate(@PathParam("id") String id);
/** /**
* Lock a server. * Lock a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean lock(String id); @Named("serverAdmin:lock")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"lock\":null}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean lock(@PathParam("id") String id);
/** /**
* Unlock a server. * Unlock a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean unlock(String id); @Named("serverAdmin:unlock")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"unlock\":null}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean unlock(@PathParam("id") String id);
/** /**
* Reset network of a server. * Reset network of a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean resetNetwork(String id); @Named("serverAdmin:resetNetwork")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"resetNetwork\":null}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean resetNetwork(@PathParam("id") String id);
/** /**
* Create backup of a server. * Create backup of a server.
@ -86,34 +137,63 @@ public interface ServerAdminApi {
* @param options optional rotation and/or metadata parameters * @param options optional rotation and/or metadata parameters
* @return the id of the newly created image * @return the id of the newly created image
*/ */
String createBackup(String id, String imageName, BackupType backupType, int rotation, CreateBackupOfServerOptions... options); @Named("serverAdmin:createBackup")
@POST
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("createBackup")
@ResponseParser(ParseImageIdFromLocationHeader.class)
@Fallback(MapHttp4xxCodesToExceptions.class)
String createBackup(@PathParam("id") String id, @PayloadParam("name") String imageName,
@PayloadParam("backup_type") BackupType backupType, @PayloadParam("rotation") int rotation,
CreateBackupOfServerOptions... options);
/** /**
* Pause a server. * Pause a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean pause(String id); @Named("serverAdmin:pause")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"pause\":null}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean pause(@PathParam("id") String id);
/** /**
* Unpause a server. * Unpause a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean unpause(String id); @Named("serverAdmin:unpause")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"unpause\":null}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean unpause(@PathParam("id") String id);
/** /**
* Live migrate a server. * Live migrate a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean liveMigrate(String id, String host, boolean blockMigration, boolean diskOverCommit); @Named("serverAdmin:liveMigrate")
@POST
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("os-migrateLive")
@Fallback(FalseOnNotFoundOr404.class)
Boolean liveMigrate(@PathParam("id") String id, @PayloadParam("host") String host,
@PayloadParam("block_migration") boolean blockMigration,
@PayloadParam("disk_over_commit") boolean diskOverCommit);
/** /**
* Inject network info into a server. * Inject network info into a server.
* *
* @param id id of the server * @param id id of the server
*/ */
Boolean injectNetworkInfo(String id); @Named("serverAdmin:injectNetwork")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"injectNetworkInfo\":null}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean injectNetworkInfo(@PathParam("id") String id);
} }

View File

@ -1,174 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.BackupType;
import org.jclouds.openstack.nova.v2_0.functions.ParseImageIdFromLocationHeader;
import org.jclouds.openstack.nova.v2_0.options.CreateBackupOfServerOptions;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provide access to Admin Server Actions via REST API
*
* @see org.jclouds.openstack.nova.v2_0.extensions.ServerAdminApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.ADMIN_ACTIONS)
@RequestFilters(AuthenticateRequest.class)
@Path("/servers/{id}/action")
public interface ServerAdminAsyncApi {
/**
* @see ServerAdminApi#suspend(String)
*/
@Named("serveradmin:suspend")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"suspend\":null}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> suspend(@PathParam("id") String id);
/**
* @see ServerAdminApi#resume(String)
*/
@Named("serveradmin:resume")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"resume\":null}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> resume(@PathParam("id") String id);
/**
* @see ServerAdminApi#migrate(String)
*/
@Named("serveradmin:migrate")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"migrate\":null}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> migrate(@PathParam("id") String id);
/**
* @see ServerAdminApi#lock(String)
*/
@Named("serveradmin:lock")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"lock\":null}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> lock(@PathParam("id") String id);
/**
* @see ServerAdminApi#unlock(String)
*/
@Named("serveradmin:unlock")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"unlock\":null}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> unlock(@PathParam("id") String id);
/**
* @see ServerAdminApi#resetNetwork(String)
*/
@Named("serveradmin:resetnetwork")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"resetNetwork\":null}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> resetNetwork(@PathParam("id") String id);
/**
* @see ServerAdminApi#createBackup
*/
@Named("serveradmin:createbackup")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("createBackup")
@Fallback(MapHttp4xxCodesToExceptions.class)
@ResponseParser(ParseImageIdFromLocationHeader.class)
ListenableFuture<String> createBackup(@PathParam("id") String id,
@PayloadParam("name") String imageName,
@PayloadParam("backup_type") BackupType backupType,
@PayloadParam("rotation") int rotation,
CreateBackupOfServerOptions... options);
/**
* @see ServerAdminApi#pause(String)
*/
@Named("serveradmin:pause")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"pause\":null}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> pause(@PathParam("id") String id);
/**
* @see ServerAdminApi#unpause(String)
*/
@Named("serveradmin:unpause")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"unpause\":null}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> unpause(@PathParam("id") String id);
/**
* @see ServerAdminApi#injectNetworkInfo(String)
*/
@Named("serveradmin:injectnetwork")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"injectNetworkInfo\":null}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> injectNetworkInfo(@PathParam("id") String id);
/**
* @see ServerAdminApi#liveMigrate(String)
*/
@Named("serveradmin:livemigrate")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
@WrapWith("os-migrateLive")
ListenableFuture<Boolean> liveMigrate(@PathParam("id") String id,
@PayloadParam("host") String host,
@PayloadParam("block_migration") boolean blockMigration,
@PayloadParam("disk_over_commit") boolean diskOverCommit);
}

View File

@ -16,33 +16,53 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.ServerWithSecurityGroups; import org.jclouds.openstack.nova.v2_0.domain.ServerWithSecurityGroups;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
/** /**
* Provides synchronous access to Server details including security group, referred to as the CREATESERVEREXT extension * Provides access to the OpenStack Compute (Nova) Create Server extension API.
* in the nova documentation *
* This provides details including the security groups associated with a Server.
* <p/> * <p/>
* NOTE: the equivalent to listServersInDetail() isn't available at the other end, so not extending ServerApi at this *
* time. * NOTE: the equivalent to listServersInDetail() isn't available at the other end, so not
* extending ServerApi at this time.
* *
* @see org.jclouds.openstack.nova.v2_0.features.ServerApi * @see org.jclouds.openstack.nova.v2_0.features.ServerApi
* @see ServerWithSecurityGroupsAsyncApi
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.createserverext.html"/>
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CREATESERVEREXT) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CREATESERVEREXT)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-create-server-ext")
public interface ServerWithSecurityGroupsApi { public interface ServerWithSecurityGroupsApi {
/** /**
* Retrieve details of the specified server, including security groups * Retrieve details of the specified server, including security groups
* *
* @param id id of the server * @param id id of the server
* @return server or null if not found * @return server or null if not found
*/ */
ServerWithSecurityGroups get(String id); @Named("server:get")
@GET
@SelectJson("server")
@Path("/{id}")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
ServerWithSecurityGroups get(@PathParam("id") String id);
} }

View File

@ -1,61 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.ServerWithSecurityGroups;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides synchronous access to Servers with Security Groups.
*
* @see org.jclouds.openstack.nova.v2_0.features.ServerAsyncApi
* @see ServerWithSecurityGroupsApi
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.createserverext.html"/>
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CREATESERVEREXT)
@RequestFilters(AuthenticateRequest.class)
public interface ServerWithSecurityGroupsAsyncApi {
/**
* @see ServerWithSecurityGroupsApi#get(String)
*/
@Named("server:get")
@GET
@SelectJson("server")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-create-server-ext/{id}")
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends ServerWithSecurityGroups> get(@PathParam("id") String id);
}

View File

@ -16,34 +16,57 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.SimpleTenantUsage; import org.jclouds.openstack.nova.v2_0.domain.SimpleTenantUsage;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides asynchronous access to Simple Tenant Usage via the REST API. * Provides access to the OpenStack Compute (Nova) Simple Tenant Usage extension API.
* <p/>
*
* @see SimpleTenantUsageAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SIMPLE_TENANT_USAGE) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SIMPLE_TENANT_USAGE)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-simple-tenant-usage")
public interface SimpleTenantUsageApi { public interface SimpleTenantUsageApi {
/** /**
* Retrieve tenant_usage for all tenants * Retrieve tenant usage for all tenants.
* *
* @return the set of TenantUsage reports * @return the set of TenantUsage reports
*/ */
FluentIterable<? extends SimpleTenantUsage> list(); @Named("tenantUsage:list")
@GET
@SelectJson("tenant_usages")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<SimpleTenantUsage> list();
/** /**
* Retrieve tenant_usage for a specified tenant * Retrieve tenant_usage for a specified tenant
* *
* @return the requested tenant usage * @return the requested tenant usage
*/ */
SimpleTenantUsage get(String tenantId); @Named("tenantUsage:get")
@GET
@Path("/{id}")
@SelectJson("tenant_usage")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
SimpleTenantUsage get(@PathParam("id") String tenantId);
} }

View File

@ -1,76 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.SimpleTenantUsage;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Simple Tenant Usage via the REST API.
* <p/>
*
* @see SimpleTenantUsageApi
* @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/nova.api.openstack.compute.contrib.simple_tenant_usage.html" />
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SIMPLE_TENANT_USAGE)
@RequestFilters(AuthenticateRequest.class)
public interface SimpleTenantUsageAsyncApi {
/**
* @see SimpleTenantUsageApi#list()
*/
@Named("tenantusage:list")
@GET
@Path("/os-simple-tenant-usage")
@SelectJson("tenant_usages")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends SimpleTenantUsage>> list();
/**
* @see SimpleTenantUsageApi#get(String)
*/
@Named("tenantusage:get")
@GET
@Path("/os-simple-tenant-usage/{id}")
@SelectJson("tenant_usage")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends SimpleTenantUsage> get(@PathParam("id") String tenantId);
}

View File

@ -16,27 +16,44 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.VirtualInterface; import org.jclouds.openstack.nova.v2_0.domain.VirtualInterface;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides synchronous access to Virtual Interface features (VIFs). * Provides access to the OpenStack Compute (Nova) Virtual Interface (VIFs) extension API.
*
* @see VirtualInterfaceAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VIRTUAL_INTERFACES) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VIRTUAL_INTERFACES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
public interface VirtualInterfaceApi { public interface VirtualInterfaceApi {
/** /**
* Returns the list of Virtual Interfaces for a given instance. * Returns the list of Virtual Interfaces for a given instance.
* *
* @return the list of snapshots * @return the list of virtual interfaces
*/ */
FluentIterable<? extends VirtualInterface> listOnServer(String serverId); @Named("virtualInterface:list")
@GET
@Path("/{id}/os-virtual-interfaces")
@SelectJson("virtual_interfaces")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<VirtualInterface> listOnServer(@PathParam("id") String serverId);
} }

View File

@ -1,58 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.VirtualInterface;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Virtual Interface features (VIFs).
*
* @see VirtualInterfaceApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VIRTUAL_INTERFACES)
@RequestFilters(AuthenticateRequest.class)
public interface VirtualInterfaceAsyncApi {
/**
* @see VirtualInterfaceApi#listOnServer(String)
*/
@Named("virtualinterface:list")
@GET
@SelectJson("virtual_interfaces")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/{server_id}/os-virtual-interfaces")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends VirtualInterface>> listOnServer(@PathParam("server_id") String serverId);
}

View File

@ -16,6 +16,21 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.Volume; import org.jclouds.openstack.nova.v2_0.domain.Volume;
import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment; import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment;
import org.jclouds.openstack.nova.v2_0.domain.VolumeSnapshot; import org.jclouds.openstack.nova.v2_0.domain.VolumeSnapshot;
@ -23,54 +38,85 @@ import org.jclouds.openstack.nova.v2_0.options.CreateVolumeOptions;
import org.jclouds.openstack.nova.v2_0.options.CreateVolumeSnapshotOptions; import org.jclouds.openstack.nova.v2_0.options.CreateVolumeSnapshotOptions;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides synchronous access to Volumes. * Provides access to the OpenStack Compute (Nova) Volume extension API.
* <p/>
*
* @see VolumeAsyncApi
* @see org.jclouds.openstack.nova.v2_0.extensions.VolumeAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface VolumeApi { public interface VolumeApi {
/** /**
* Returns a summary list of snapshots. * Returns a summary list of snapshots.
* *
* @return the list of snapshots * @return the list of snapshots
*/ */
FluentIterable<? extends Volume> list(); @Named("volume:list")
@GET
@Path("/os-volumes")
@SelectJson("volumes")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<Volume> list();
/** /**
* Returns a detailed list of volumes. * Returns a detailed list of volumes.
* *
* @return the list of volumes. * @return the list of volumes.
*/ */
FluentIterable<? extends Volume> listInDetail(); @Named("volume:list")
@GET
@Path("/os-volumes/detail")
@SelectJson("volumes")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<Volume> listInDetail();
/** /**
* Return data about the given volume. * Return data about the given volume.
* *
* @return details of a specific snapshot. * @return details of a specific snapshot.
*/ */
Volume get(String volumeId); @Named("volume:get")
@GET
@Path("/os-volumes/{id}")
@SelectJson("volume")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Volume get(@PathParam("id") String volumeId);
/** /**
* Creates a new Snapshot * Creates a new Snapshot
* *
* @return the new Snapshot * @return the new Snapshot
*/ */
Volume create(int sizeGB, CreateVolumeOptions... options); @Named("volume:create")
@POST
@Path("/os-volumes")
@SelectJson("volume")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(CreateVolumeOptions.class)
Volume create(@PayloadParam("size") int sizeGB, CreateVolumeOptions... options);
/** /**
* Delete a snapshot. * Delete a snapshot.
* *
* @return true if successful * @return true if successful
*/ */
boolean delete(String volumeId); @Named("volume:delete")
@DELETE
@Path("/os-volumes/{volumeId}")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
boolean delete(@PathParam("volumeId") String volumeId);
/** /**
* List volume attachments for a given instance. * List volume attachments for a given instance.
@ -79,7 +125,14 @@ public interface VolumeApi {
* @deprecated To be removed in jclouds 1.7 * @deprecated To be removed in jclouds 1.7
* @see VolumeAttachmentApi#listAttachmentsOnServer(String) * @see VolumeAttachmentApi#listAttachmentsOnServer(String)
*/ */
@Deprecated FluentIterable<? extends VolumeAttachment> listAttachmentsOnServer(String serverId); @Deprecated
@Named("volume:listAttachments")
@GET
@Path("/servers/{id}/os-volume_attachments")
@SelectJson("volumeAttachments")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<VolumeAttachment> listAttachmentsOnServer(@PathParam("id") String serverId);
/** /**
* Get a specific attached volume. * Get a specific attached volume.
@ -88,7 +141,16 @@ public interface VolumeApi {
* @deprecated To be removed in jclouds 1.7 * @deprecated To be removed in jclouds 1.7
* @see VolumeAttachmentApi#getAttachmentForVolumeOnServer(String, String) * @see VolumeAttachmentApi#getAttachmentForVolumeOnServer(String, String)
*/ */
@Deprecated VolumeAttachment getAttachmentForVolumeOnServer(String volumeId, String serverId); @Deprecated
@Named("volume:getAttachments")
@GET
@Path("/servers/{serverId}/os-volume_attachments/{id}")
@SelectJson("volumeAttachment")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
VolumeAttachment getAttachmentForVolumeOnServer(@PathParam("id") String volumeId,
@PathParam("serverId") String serverId);
/** /**
* Attach a volume to an instance * Attach a volume to an instance
@ -97,7 +159,15 @@ public interface VolumeApi {
* @deprecated To be removed in jclouds 1.7 * @deprecated To be removed in jclouds 1.7
* @see VolumeAttachmentApi#attachVolumeToServerAsDevice(String, String, String) * @see VolumeAttachmentApi#attachVolumeToServerAsDevice(String, String, String)
*/ */
@Deprecated VolumeAttachment attachVolumeToServerAsDevice(String volumeId, String serverId, String device); @Deprecated
@Named("volume:attach")
@POST
@Path("/servers/{serverId}/os-volume_attachments")
@SelectJson("volumeAttachment")
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("volumeAttachment")
VolumeAttachment attachVolumeToServerAsDevice(@PayloadParam("volumeId") String volumeId,
@PathParam("serverId") String serverId, @PayloadParam("device") String device);
/** /**
* Detach a Volume from an instance. * Detach a Volume from an instance.
@ -106,41 +176,72 @@ public interface VolumeApi {
* @deprecated To be removed in jclouds 1.7 * @deprecated To be removed in jclouds 1.7
* @see VolumeAttachmentApi#detachVolumeFromServer(String, String) * @see VolumeAttachmentApi#detachVolumeFromServer(String, String)
*/ */
@Deprecated Boolean detachVolumeFromServer(String server_id, String volumeId); @Deprecated
@Named("volume:detach")
@DELETE
@Path("/servers/{serverId}/os-volume_attachments/{id}")
@Fallback(FalseOnNotFoundOr404.class)
Boolean detachVolumeFromServer(@PathParam("id") String volumeId,
@PathParam("serverId") String serverId);
/** /**
* Returns a summary list of snapshots. * Returns a summary list of snapshots.
* *
* @return the list of snapshots * @return the list of snapshots
*/ */
FluentIterable<? extends VolumeSnapshot> listSnapshots(); @Named("volume:listSnapshots")
@GET
@Path("/os-snapshots")
@SelectJson("snapshots")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<VolumeSnapshot> listSnapshots();
/** /**
* Returns a summary list of snapshots. * Returns a summary list of snapshots.
* *
* @return the list of snapshots * @return the list of snapshots
*/ */
FluentIterable<? extends VolumeSnapshot> listSnapshotsInDetail(); @Named("volume:listSnapshots")
@GET
@Path("/os-snapshots/detail")
@SelectJson("snapshots")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<VolumeSnapshot> listSnapshotsInDetail();
/** /**
* Return data about the given snapshot. * Return data about the given snapshot.
* *
* @return details of a specific snapshot. * @return details of a specific snapshot.
*/ */
VolumeSnapshot getSnapshot(String snapshotId); @Named("volume:getSnapshot")
@GET
@Path("/os-snapshots/{id}")
@SelectJson("snapshot")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
VolumeSnapshot getSnapshot(@PathParam("id") String snapshotId);
/** /**
* Creates a new Snapshot * Creates a new Snapshot.
* *
* @return the new Snapshot * @return the new Snapshot
*/ */
VolumeSnapshot createSnapshot(String volumeId, CreateVolumeSnapshotOptions... options); @Named("volume:createSnapshot")
@POST
@Path("/os-snapshots")
@SelectJson("snapshot")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(CreateVolumeSnapshotOptions.class)
VolumeSnapshot createSnapshot(@PayloadParam("volume_id") String volumeId, CreateVolumeSnapshotOptions... options);
/** /**
* Delete a snapshot. * Delete a snapshot.
* *
* @return true if successful * @return true if successful
*/ */
boolean deleteSnapshot(String snapshotId); @Named("volume:deleteSnapshot")
@DELETE
@Path("/os-snapshots/{id}")
@Fallback(FalseOnNotFoundOr404.class)
boolean deleteSnapshot(@PathParam("id") String snapshotId);
} }

View File

@ -1,253 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.Volume;
import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment;
import org.jclouds.openstack.nova.v2_0.domain.VolumeSnapshot;
import org.jclouds.openstack.nova.v2_0.options.CreateVolumeOptions;
import org.jclouds.openstack.nova.v2_0.options.CreateVolumeSnapshotOptions;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides synchronous access to Volumes.
* <p/>
*
* @see org.jclouds.openstack.nova.v2_0.extensions.VolumeAsyncApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES)
@RequestFilters(AuthenticateRequest.class)
public interface VolumeAsyncApi {
/**
* Returns a summary list of volumes.
*
* @return the list of volumes
*/
@Named("volume:list")
@GET
@Path("/os-volumes")
@SelectJson("volumes")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends Volume>> list();
/**
* Returns a detailed list of volumes.
*
* @return the list of volumes.
*/
@Named("volume:list")
@GET
@Path("/os-volumes/detail")
@SelectJson("volumes")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends Volume>> listInDetail();
/**
* Return data about the given volume.
*
* @return details of a specific volume.
*/
@Named("volume:get")
@GET
@Path("/os-volumes/{id}")
@SelectJson("volume")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends Volume> get(@PathParam("id") String volumeId);
/**
* Creates a new volume
*
* @return the new Snapshot
*/
@Named("volume:create")
@POST
@Path("/os-volumes")
@SelectJson("volume")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(CreateVolumeOptions.class)
ListenableFuture<? extends Volume> create(@PayloadParam("size") int sizeGB, CreateVolumeOptions... options);
/**
* Delete a volume.
*
* @return true if successful
*/
@Named("volume:delete")
@DELETE
@Path("/os-volumes/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> delete(@PathParam("id") String volumeId);
/**
* List volume attachments for a given instance.
*
* @return all Floating IPs
* @deprecated To be removed in jclouds 1.7
* @see VolumeAttachmentApi#listAttachmentsOnServer(String)
*/
@Named("volume:listattachments")
@GET
@Path("/servers/{server_id}/os-volume_attachments")
@SelectJson("volumeAttachments")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
@Deprecated ListenableFuture<? extends FluentIterable<? extends VolumeAttachment>> listAttachmentsOnServer(@PathParam("server_id") String serverId);
/**
* Get a specific attached volume.
*
* @return data about the given volume attachment.
* @deprecated To be removed in jclouds 1.7
* @see VolumeAttachmentApi#getAttachmentForVolumeOnServer(String, String)
*/
@Named("volume:getattachments")
@GET
@Path("/servers/{server_id}/os-volume_attachments/{id}")
@SelectJson("volumeAttachment")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Deprecated ListenableFuture<? extends VolumeAttachment> getAttachmentForVolumeOnServer(@PathParam("id") String volumeId,
@PathParam("server_id") String serverId);
/**
* Attach a volume to an instance
*
* @return the new Attachment
* @deprecated To be removed in jclouds 1.7
* @see VolumeAttachmentApi#attachVolumeToServerAsDevice(String, String, String)
*/
@Named("volume:attach")
@POST
@Path("/servers/{server_id}/os-volume_attachments")
@SelectJson("volumeAttachment")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@WrapWith("volumeAttachment")
@Deprecated ListenableFuture<? extends VolumeAttachment> attachVolumeToServerAsDevice(@PayloadParam("volumeId") String volumeId,
@PathParam("server_id") String serverId, @PayloadParam("device") String device);
/**
* Detach a Volume from an instance.
*
* @return true if successful
* @deprecated To be removed in jclouds 1.7
* @see VolumeAttachmentApi#detachVolumeFromServer(String, String)
*/
@Named("volume:detach")
@DELETE
@Path("/servers/{server_id}/os-volume_attachments/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
@Deprecated ListenableFuture<Boolean> detachVolumeFromServer(@PathParam("id") String volumeId, @PathParam("server_id") String serverId);
/**
* Returns a summary list of snapshots.
*
* @return the list of snapshots
*/
@Named("volume:listsnapshots")
@GET
@Path("/os-snapshots")
@SelectJson("snapshots")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends VolumeSnapshot>> listSnapshots();
/**
* Returns a summary list of snapshots.
*
* @return the list of snapshots
*/
@Named("volume:listsnapshot")
@GET
@Path("/os-snapshots/detail")
@SelectJson("snapshots")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends VolumeSnapshot>> listSnapshotsInDetail();
/**
* Return data about the given snapshot.
*
* @return details of a specific snapshot.
*/
@Named("volume:getsnapshot")
@GET
@Path("/os-snapshots/{id}")
@SelectJson("snapshot")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends VolumeSnapshot> getSnapshot(@PathParam("id") String snapshotId);
/**
* Creates a new Snapshot
*
* @return the new Snapshot
*/
@Named("volume:createsnapshot")
@POST
@Path("/os-snapshots")
@SelectJson("snapshot")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@MapBinder(CreateVolumeSnapshotOptions.class)
ListenableFuture<? extends VolumeSnapshot> createSnapshot(@PayloadParam("volume_id") String volumeId, CreateVolumeSnapshotOptions... options);
/**
* Delete a snapshot.
*
* @return true if successful
*/
@Named("volume:deletesnapshot")
@DELETE
@Path("/os-snapshots/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> deleteSnapshot(@PathParam("id") String snapshotId);
}

View File

@ -16,15 +16,35 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment; import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides synchronous access to Volume Attachments. * Provides access to the OpenStack Compute (Nova) Volume Attachments Extension API.
* *
* This API strictly handles attaching Volumes to Servers. To create and manage Volumes you need to use one of the * This API strictly handles attaching Volumes to Servers. To create and manage Volumes you need to use one of the
* following APIs: * following APIs:
@ -37,10 +57,12 @@ import com.google.common.collect.FluentIterable;
* If your OpenStack deployment is Essex or earlier and it supports the nova-volume extension, use this API. * If your OpenStack deployment is Essex or earlier and it supports the nova-volume extension, use this API.
* @see org.jclouds.openstack.nova.v2_0.extensions.VolumeApi * @see org.jclouds.openstack.nova.v2_0.extensions.VolumeApi
* *
* @see VolumeAttachmentAsyncApi
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
public interface VolumeAttachmentApi { public interface VolumeAttachmentApi {
/** /**
* List Volume Attachments for a given Server. * List Volume Attachments for a given Server.
@ -48,7 +70,12 @@ public interface VolumeAttachmentApi {
* @param serverId The ID of the Server * @param serverId The ID of the Server
* @return All VolumeAttachments for the Server * @return All VolumeAttachments for the Server
*/ */
FluentIterable<? extends VolumeAttachment> listAttachmentsOnServer(String serverId); @Named("volumeAttachment:list")
@GET
@Path("/{serverId}/os-volume_attachments")
@SelectJson("volumeAttachments")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<VolumeAttachment> listAttachmentsOnServer(@PathParam("serverId") String serverId);
/** /**
* Get a specific Volume Attachment for a Volume and Server. * Get a specific Volume Attachment for a Volume and Server.
@ -57,7 +84,14 @@ public interface VolumeAttachmentApi {
* @param serverId The ID of the Server * @param serverId The ID of the Server
* @return The Volume Attachment. * @return The Volume Attachment.
*/ */
VolumeAttachment getAttachmentForVolumeOnServer(String volumeId, String serverId); @Named("volumeAttachment:get")
@GET
@Path("/{serverId}/os-volume_attachments/{id}")
@SelectJson("volumeAttachment")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
VolumeAttachment getAttachmentForVolumeOnServer(@PathParam("id") String volumeId,
@PathParam("serverId") String serverId);
/** /**
* Attach a Volume to a Server. * Attach a Volume to a Server.
@ -71,7 +105,14 @@ public interface VolumeAttachmentApi {
* @param device The name of the device this Volume will be identified as in the Server (e.g. /dev/vdc) * @param device The name of the device this Volume will be identified as in the Server (e.g. /dev/vdc)
* @return The Volume Attachment. * @return The Volume Attachment.
*/ */
VolumeAttachment attachVolumeToServerAsDevice(String volumeId, String serverId, String device); @Named("volumeAttachment:attach")
@POST
@Path("/{serverId}/os-volume_attachments")
@SelectJson("volumeAttachment")
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("volumeAttachment")
VolumeAttachment attachVolumeToServerAsDevice(@PayloadParam("volumeId") String volumeId,
@PathParam("serverId") String serverId, @PayloadParam("device") String device);
/** /**
* Detach a Volume from a server. * Detach a Volume from a server.
@ -82,5 +123,10 @@ public interface VolumeAttachmentApi {
* @param serverId The ID of the Server * @param serverId The ID of the Server
* @return true if successful * @return true if successful
*/ */
boolean detachVolumeFromServer(String volumeId, String serverId); @Named("volumeAttachment:detach")
@DELETE
@Path("/{serverId}/os-volume_attachments/{id}")
@Fallback(FalseOnNotFoundOr404.class)
boolean detachVolumeFromServer(@PathParam("id") String volumeId,
@PathParam("serverId") String serverId);
} }

View File

@ -1,106 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Volume Attachments .
*
* @see VolumeAttachmentApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES)
@RequestFilters(AuthenticateRequest.class)
public interface VolumeAttachmentAsyncApi {
/**
* @see VolumeAttachmentApi#listAttachmentsOnServer(String)
*/
@Named("volumeattachment:list")
@GET
@Path("/servers/{server_id}/os-volume_attachments")
@SelectJson("volumeAttachments")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends VolumeAttachment>> listAttachmentsOnServer(
@PathParam("server_id") String serverId);
/**
* @see VolumeAttachmentApi#getAttachmentForVolumeOnServer(String, String)
*/
@Named("volumeattachment:get")
@GET
@Path("/servers/{server_id}/os-volume_attachments/{id}")
@SelectJson("volumeAttachment")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends VolumeAttachment> getAttachmentForVolumeOnServer(
@PathParam("id") String volumeId,
@PathParam("server_id") String serverId);
/**
* @see VolumeAttachmentApi#attachVolumeToServerAsDevice(String, String, String)
*/
@Named("volumeattachment:attach")
@POST
@Path("/servers/{server_id}/os-volume_attachments")
@SelectJson("volumeAttachment")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@WrapWith("volumeAttachment")
ListenableFuture<? extends VolumeAttachment> attachVolumeToServerAsDevice(
@PayloadParam("volumeId") String volumeId,
@PathParam("server_id") String serverId,
@PayloadParam("device") String device);
/**
* @see VolumeAttachmentApi#detachVolumeFromServer(String, String)
*/
@Named("volumeattachment:detach")
@DELETE
@Path("/servers/{server_id}/os-volume_attachments/{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> detachVolumeFromServer(
@PathParam("id") String volumeId,
@PathParam("server_id") String serverId);
}

View File

@ -17,36 +17,74 @@
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import java.util.Map; import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.VolumeType; import org.jclouds.openstack.nova.v2_0.domain.VolumeType;
import org.jclouds.openstack.nova.v2_0.options.CreateVolumeTypeOptions; import org.jclouds.openstack.nova.v2_0.options.CreateVolumeTypeOptions;
import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.annotations.WrapWith;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides synchronous access to Volume Type features * Provides access to the OpenStack Compute (Nova) Volume Type extension API.
* *
* @see VolumeApi * @see VolumeApi
* @see VolumeTypeAsyncApi
* @see <a href="http://nova.openstack.org/api/nova.api.openstack.compute.contrib.volumetypes.html"/>
* @see <a href="https://blueprints.launchpad.net/nova/+spec/volume-type"/>
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUME_TYPES) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUME_TYPES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-volume-types")
public interface VolumeTypeApi { public interface VolumeTypeApi {
/** /**
* @return set of all volume types * @return set of all volume types
*/ */
FluentIterable<? extends VolumeType> list(); @Named("volumeType:list")
@GET
@SelectJson("volume_types")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<VolumeType> list();
/** /**
* Gets a volume type
*
* @param id the id of the volume type to retrieve * @param id the id of the volume type to retrieve
* @return the requested volume type * @return the requested volume type
*/ */
VolumeType get(String id); @Named("volumeType:get")
@GET
@Path("/{id}")
@SelectJson("volume_type")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
VolumeType get(@PathParam("id") String id);
/** /**
* Creates a new volume type * Creates a new volume type
@ -55,23 +93,47 @@ public interface VolumeTypeApi {
* @param options optional settings for the new volume type * @param options optional settings for the new volume type
* @return the new volume type * @return the new volume type
*/ */
VolumeType create(String name, CreateVolumeTypeOptions... options); @Named("volumeType:create")
@POST
@SelectJson("volume_type")
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("volume_type")
VolumeType create(@PayloadParam("name") String name, CreateVolumeTypeOptions... options);
/** /**
* Deletes a volume type * Deletes a volume type
*
* @param id the id of the volume type to delete
*/ */
boolean delete(String id); @Named("volumeType:delete")
@DELETE
@Path("/{id}")
@Fallback(FalseOnNotFoundOr404.class)
boolean delete(@PathParam("id") String id);
/** /**
* Gets the extra specs for a volume type
*
* @param id the id of the volume type * @param id the id of the volume type
* @return the set of extra metadata for the flavor * @return the set of extra metadata for the flavor
*/ */
Map<String, String> getExtraSpecs(String id); @Named("volumeType:getExtraSpecs")
@GET
@Path("/{id}/extra_specs")
@SelectJson("extra_specs")
@Fallback(EmptyMapOnNotFoundOr404.class)
Map<String, String> getExtraSpecs(@PathParam("id") String id);
/** /**
* Creates or updates the extra metadata for a given flavor * Creates or updates the extra metadata for a given flavor
*/ */
boolean updateExtraSpecs(String id, Map<String, String> specs); @Named("volumeType:updateExtraSpecs")
@POST
@Path("/{id}/extra_specs")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindToJsonPayload.class)
@Fallback(FalseOnNotFoundOr404.class)
boolean updateExtraSpecs(@PathParam("id") String id, @PayloadParam("extra_specs") Map<String, String> specs);
/** /**
* Retrieve a single extra spec value * Retrieve a single extra spec value
@ -79,7 +141,13 @@ public interface VolumeTypeApi {
* @param id the id of the volume type * @param id the id of the volume type
* @param key the key of the extra spec item to retrieve * @param key the key of the extra spec item to retrieve
*/ */
String getExtraSpec(String id, String key); @Named("volumeType:getExtraSpec")
@GET
@Path("/{id}/extra_specs/{key}")
@Unwrap
@Fallback(NullOnNotFoundOr404.class)
@Nullable
String getExtraSpec(@PathParam("id") String id, @PathParam("key") String key);
/** /**
* Creates or updates a single extra spec value * Creates or updates a single extra spec value
@ -88,7 +156,15 @@ public interface VolumeTypeApi {
* @param key the extra spec key (when creating ensure this does not include whitespace or other difficult characters) * @param key the extra spec key (when creating ensure this does not include whitespace or other difficult characters)
* @param value the new value to store associate with the key * @param value the new value to store associate with the key
*/ */
boolean updateExtraSpec(String id, String key, String value); @Named("volumeType:updateExtraSpec")
@PUT
@Path("/{id}/extra_specs/{key}")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"{key}\":\"{value}\"%7D")
@Fallback(FalseOnNotFoundOr404.class)
boolean updateExtraSpec(@PathParam("id") String id,
@PathParam("key") @PayloadParam("key") String key,
@PayloadParam("value") String value);
/** /**
* Deletes an existing extra spec * Deletes an existing extra spec
@ -96,5 +172,9 @@ public interface VolumeTypeApi {
* @param id the id of the volume type * @param id the id of the volume type
* @param key the key of the extra spec to delete * @param key the key of the extra spec to delete
*/ */
boolean deleteExtraSpec(String id, String key); @Named("volumeType:deleteExtraSpec")
@DELETE
@Path("/{id}/extra_specs/{key}")
@Fallback(FalseOnNotFoundOr404.class)
boolean deleteExtraSpec(@PathParam("id") String id, @PathParam("key") String key);
} }

View File

@ -1,160 +0,0 @@
/*
* 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.openstack.nova.v2_0.extensions;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.VolumeType;
import org.jclouds.openstack.nova.v2_0.options.CreateVolumeTypeOptions;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.services.Extension;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.annotations.WrapWith;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Volume Type features
*
* @see VolumeTypeApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUME_TYPES)
@RequestFilters(AuthenticateRequest.class)
@Path("/os-volume-types")
@Consumes(MediaType.APPLICATION_JSON)
public interface VolumeTypeAsyncApi {
/**
* @see VolumeTypeApi#list
*/
@Named("volumetype:list")
@GET
@SelectJson("volume_types")
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends VolumeType>> list();
/**
* @see VolumeTypeApi#get
*/
@Named("volumetype:get")
@GET
@Path("/{id}")
@SelectJson("volume_type")
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends VolumeType> get(@PathParam("id") String id);
/**
* @see VolumeTypeApi#create
*/
@Named("volumetype:create")
@POST
@SelectJson("volume_type")
@Produces(MediaType.APPLICATION_JSON)
@WrapWith("volume_type")
ListenableFuture<? extends VolumeType> create(@PayloadParam("name") String name, CreateVolumeTypeOptions... options);
/**
* @see VolumeTypeApi#delete
*/
@Named("volumetype:delete")
@DELETE
@Path("/{id}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> delete(@PathParam("id") String id);
/**
* @see VolumeTypeApi#getExtraSpecs(String)
*/
@Named("volumetype:getextraspecs")
@GET
@SelectJson("extra_specs")
@Path("/{id}/extra_specs")
@Fallback(EmptyMapOnNotFoundOr404.class)
ListenableFuture<Map<String, String>> getExtraSpecs(@PathParam("id") String id);
/**
* @see VolumeTypeApi#updateExtraSpecs(String, java.util.Map)
*/
@Named("volumetype:udpateextraspecs")
@POST
@Path("/{id}/extra_specs")
@Produces(MediaType.APPLICATION_JSON)
@Fallback(FalseOnNotFoundOr404.class)
@MapBinder(BindToJsonPayload.class)
ListenableFuture<Boolean> updateExtraSpecs(@PathParam("id") String id, @PayloadParam("extra_specs") Map<String, String> specs);
/**
* @see VolumeTypeApi#getExtraSpec(String, String)
*/
@Named("volumetype:getextraspec")
@GET
@Path("/{id}/extra_specs/{key}")
@Unwrap
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<String> getExtraSpec(@PathParam("id") String id, @PathParam("key") String key);
/**
* @see VolumeTypeApi#updateExtraSpec(String, String, String)
*/
@Named("volumetype:updateextraspec")
@PUT
@Path("/{id}/extra_specs/{key}")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"{key}\":\"{value}\"%7D")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> updateExtraSpec(@PathParam("id") String id,
@PathParam("key") @PayloadParam("key") String key,
@PayloadParam("value") String value);
/**
* @see VolumeTypeApi#deleteExtraSpec(String, String)
*/
@Named("volumetype:deleteextraspec")
@DELETE
@Path("/{id}/extra_specs/{key}")
@Fallback(FalseOnNotFoundOr404.class)
ListenableFuture<Boolean> deleteExtraSpec(@PathParam("id") String id,
@PathParam("key") String key);
}

View File

@ -16,40 +16,83 @@
*/ */
package org.jclouds.openstack.nova.v2_0.features; package org.jclouds.openstack.nova.v2_0.features;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.collect.PagedIterable; import org.jclouds.collect.PagedIterable;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.Flavor; import org.jclouds.openstack.nova.v2_0.domain.Flavor;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseFlavorDetails;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseFlavors;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
import org.jclouds.openstack.v2_0.domain.Resource; import org.jclouds.openstack.v2_0.domain.Resource;
import org.jclouds.openstack.v2_0.options.PaginationOptions; import org.jclouds.openstack.v2_0.options.PaginationOptions;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.annotations.WrapWith;
/** /**
* Provides asynchronous access to Flavors via their REST API. * Provides access to the OpenStack Compute (Nova) Flavor API.
* <p/> * <p/>
* *
* @see FlavorAsyncApi
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/2/content/List_Flavors-d1e4188.html"
* />
*/ */
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors")
public interface FlavorApi { public interface FlavorApi {
/** /**
* List all flavors (IDs, names, links) * List all flavors (IDs, names, links)
* *
* @return all flavors (IDs, names, links) * @return all flavors (IDs, names, links)
*/ */
PagedIterable<? extends Resource> list(); @Named("flavor:list")
@GET
@ResponseParser(ParseFlavors.class)
@Transform(ParseFlavors.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Resource> list();
PaginatedCollection<? extends Resource> list(PaginationOptions options); @Named("flavor:list")
@GET
@ResponseParser(ParseFlavors.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
PaginatedCollection<Resource> list(PaginationOptions options);
/** /**
* List all flavors (all details) * List all flavors (all details)
* *
* @return all flavors (all details) * @return all flavors (all details)
*/ */
PagedIterable<? extends Flavor> listInDetail(); @Named("flavor:list")
@GET
@Path("/detail")
@ResponseParser(ParseFlavorDetails.class)
@Transform(ParseFlavorDetails.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Flavor> listInDetail();
PaginatedCollection<? extends Flavor> listInDetail(PaginationOptions options); @Named("flavor:list")
@GET
@Path("/detail")
@ResponseParser(ParseFlavorDetails.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
PaginatedCollection<Flavor> listInDetail(PaginationOptions options);
/** /**
* List details of the specified flavor * List details of the specified flavor
@ -58,7 +101,13 @@ public interface FlavorApi {
* id of the flavor * id of the flavor
* @return flavor or null if not found * @return flavor or null if not found
*/ */
Flavor get(String id); @Named("flavor:get")
@GET
@Path("/{id}")
@SelectJson("flavor")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Flavor get(@PathParam("id") String id);
/** /**
* Create flavor according to the provided object * Create flavor according to the provided object
@ -66,12 +115,22 @@ public interface FlavorApi {
* @param flavor - flavor object * @param flavor - flavor object
* @return newly created flavor * @return newly created flavor
*/ */
Flavor create(Flavor flavor); @Named("flavor:create")
@POST
@Unwrap
@Produces(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Flavor create(@WrapWith("flavor") Flavor flavor);
/** /**
* Delete flavor with a given id * Delete flavor with a given id
* *
* @param id - flavor id * @param id - flavor id
*/ */
void delete(String id); @Named("flavor:delete")
@DELETE
@Path("/{id}")
@Fallback(VoidOnNotFoundOr404.class)
void delete(@PathParam("id") String id);
} }

View File

@ -1,142 +0,0 @@
/*
* 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.openstack.nova.v2_0.features;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.domain.Flavor;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseFlavorDetails;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseFlavors;
import org.jclouds.openstack.v2_0.domain.Resource;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.annotations.WrapWith;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Flavors via their REST API.
* <p/>
*
* @see FlavorApi
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/2/content/List_Flavors-d1e4188.html"
* >docs</a>
*/
// TODO: Need a ListFlavorOptions class minDisk=minDiskInGB&minRam=minRamInMB& marker=markerID&limit=int
@RequestFilters(AuthenticateRequest.class)
public interface FlavorAsyncApi {
/**
* @see FlavorApi#list()
*/
@Named("flavor:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseFlavors.class)
@Transform(ParseFlavors.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
ListenableFuture<? extends PagedIterable<? extends Resource>> list();
/** @see FlavorApi#list(PaginationOptions) */
@Named("flavor:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseFlavors.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
ListenableFuture<? extends PaginatedCollection<? extends Resource>> list(PaginationOptions options);
/**
* @see FlavorApi#listInDetail()
*/
@Named("flavor:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors/detail")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseFlavorDetails.class)
@Transform(ParseFlavorDetails.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
ListenableFuture<? extends PagedIterable<? extends Flavor>> listInDetail();
/** @see FlavorApi#listInDetail(PaginationOptions) */
@Named("flavor:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors/detail")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseFlavorDetails.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
ListenableFuture<? extends PaginatedCollection<? extends Flavor>> listInDetail(PaginationOptions options);
/**
* @see FlavorApi#get
*/
@Named("flavor:get")
@GET
@SelectJson("flavor")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors/{id}")
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends Flavor> get(@PathParam("id") String id);
/**
* @see FlavorApi#create
*/
@Named("flavor:create")
@POST
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/flavors")
ListenableFuture<? extends Flavor> create(@WrapWith("flavor") Flavor flavor);
/**
* @see FlavorApi#delete
*/
@Named("flavor:delete")
@DELETE
@Consumes
@Path("/flavors/{id}")
@Fallback(VoidOnNotFoundOr404.class)
ListenableFuture<Void> delete(@PathParam("id") String id);
}

View File

@ -17,41 +17,87 @@
package org.jclouds.openstack.nova.v2_0.features; package org.jclouds.openstack.nova.v2_0.features;
import java.util.Map; import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.collect.PagedIterable; import org.jclouds.collect.PagedIterable;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection; import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindMetadataToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.Image; import org.jclouds.openstack.nova.v2_0.domain.Image;
import org.jclouds.openstack.nova.v2_0.functions.internal.OnlyMetadataValueOrNull;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseImageDetails;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseImages;
import org.jclouds.openstack.v2_0.domain.Resource; import org.jclouds.openstack.v2_0.domain.Resource;
import org.jclouds.openstack.v2_0.options.PaginationOptions; import org.jclouds.openstack.v2_0.options.PaginationOptions;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.binders.BindToJsonPayload;
/** /**
* Provides synchronous access to Images. * Provides access to the OpenStack Compute (Nova) Image API.
* <p/>
*
* @see ImageAsyncApi
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/1.1/content/Servers-d1e2073.html"
* />
*/ */
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
public interface ImageApi { public interface ImageApi {
/** /**
* List all images (IDs, names, links) * List all images (IDs, names, links)
* *
* @return all images (IDs, names, links) * @return all images (IDs, names, links)
*/ */
PagedIterable<? extends Resource> list(); @Named("image:list")
@GET
@ResponseParser(ParseImages.class)
@Transform(ParseImages.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Resource> list();
PaginatedCollection<? extends Resource> list(PaginationOptions options); @Named("image:list")
@GET
@ResponseParser(ParseImages.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
PaginatedCollection<Resource> list(PaginationOptions options);
/** /**
* List all images (all details) * List all images (all details)
* *
* @return all images (all details) * @return all images (all details)
*/ */
PagedIterable<? extends Image> listInDetail(); @Named("image:list")
@GET
@Path("/detail")
@ResponseParser(ParseImageDetails.class)
@Transform(ParseImageDetails.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Image> listInDetail();
PaginatedCollection<? extends Image> listInDetail(PaginationOptions options); @Named("image:list")
@GET
@Path("/detail")
@ResponseParser(ParseImageDetails.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
PaginatedCollection<Image> listInDetail(PaginationOptions options);
/** /**
* List details of the specified image * List details of the specified image
@ -60,7 +106,13 @@ public interface ImageApi {
* id of the server * id of the server
* @return server or null if not found * @return server or null if not found
*/ */
Image get(String id); @Named("image:get")
@GET
@Path("/{id}")
@SelectJson("image")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Image get(@PathParam("id") String id);
/** /**
* Delete the specified image * Delete the specified image
@ -69,7 +121,11 @@ public interface ImageApi {
* id of the image * id of the image
* @return server or null if not found * @return server or null if not found
*/ */
void delete(String id); @Named("image:delete")
@DELETE
@Path("/{id}")
@Fallback(VoidOnNotFoundOr404.class)
void delete(@PathParam("id") String id);
/** /**
* List all metadata for an image. * List all metadata for an image.
@ -78,7 +134,12 @@ public interface ImageApi {
* id of the image * id of the image
* @return the metadata as a Map<String, String> * @return the metadata as a Map<String, String>
*/ */
Map<String, String> getMetadata(String id); @Named("image:getMetadata")
@GET
@Path("/{id}/metadata")
@SelectJson("metadata")
@Fallback(EmptyMapOnNotFoundOr404.class)
Map<String, String> getMetadata(@PathParam("id") String id);
/** /**
* Sets the metadata for an image. * Sets the metadata for an image.
@ -89,7 +150,14 @@ public interface ImageApi {
* a Map containing the metadata * a Map containing the metadata
* @return the metadata as a Map<String, String> * @return the metadata as a Map<String, String>
*/ */
Map<String, String> setMetadata(String id, Map<String, String> metadata); @Named("image:setMetadata")
@PUT
@Path("/{id}/metadata")
@SelectJson("metadata")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindToJsonPayload.class)
@Fallback(EmptyMapOnNotFoundOr404.class)
Map<String, String> setMetadata(@PathParam("id") String id, @PayloadParam("metadata") Map<String, String> metadata);
/** /**
* Update the metadata for a server. * Update the metadata for a server.
@ -100,7 +168,14 @@ public interface ImageApi {
* a Map containing the metadata * a Map containing the metadata
* @return the metadata as a Map<String, String> * @return the metadata as a Map<String, String>
*/ */
Map<String, String> updateMetadata(String id, Map<String, String> metadata); @Named("image:updateMetadata")
@POST
@Path("/{id}/metadata")
@SelectJson("metadata")
@Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindToJsonPayload.class)
@Fallback(EmptyMapOnNotFoundOr404.class)
Map<String, String> updateMetadata(@PathParam("id") String id, @PayloadParam("metadata") Map<String, String> metadata);
/** /**
* Update the metadata for an image. * Update the metadata for an image.
@ -111,9 +186,13 @@ public interface ImageApi {
* a Map containing the metadata * a Map containing the metadata
* @return the value or null if not present * @return the value or null if not present
*/ */
@Named("image:getMetadata")
@GET
@Path("/{id}/metadata/{key}")
@ResponseParser(OnlyMetadataValueOrNull.class)
@Fallback(NullOnNotFoundOr404.class)
@Nullable @Nullable
String getMetadata(String id, String key); String getMetadata(@PathParam("id") String id, @PathParam("key") String key);
/** /**
* Set a metadata item for an image. * Set a metadata item for an image.
@ -126,7 +205,15 @@ public interface ImageApi {
* the value of the metadata item * the value of the metadata item
* @return the value you updated * @return the value you updated
*/ */
String updateMetadata(String id, String key, String value); @Named("image:updateMetadata")
@PUT
@Path("/{id}/metadata/{key}")
@ResponseParser(OnlyMetadataValueOrNull.class)
@MapBinder(BindMetadataToJsonPayload.class)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
String updateMetadata(@PathParam("id") String id, @PathParam("key") @PayloadParam("key") String key,
@PathParam("value") @PayloadParam("value") String value);
/** /**
* Delete a metadata item from an image. * Delete a metadata item from an image.
@ -136,6 +223,9 @@ public interface ImageApi {
* @param key * @param key
* the name of the metadata item * the name of the metadata item
*/ */
void deleteMetadata(String id, String key); @Named("image:deleteMetadata")
@DELETE
@Path("/{id}/metadata/{key}")
@Fallback(VoidOnNotFoundOr404.class)
void deleteMetadata(@PathParam("id") String id, @PathParam("key") String key);
} }

View File

@ -1,205 +0,0 @@
/*
* 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.openstack.nova.v2_0.features;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindMetadataToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.Image;
import org.jclouds.openstack.nova.v2_0.functions.internal.OnlyMetadataValueOrNull;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseImageDetails;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseImages;
import org.jclouds.openstack.v2_0.domain.Resource;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Images via the REST API.
* <p/>
*
* @see ImageApi
*/
@RequestFilters(AuthenticateRequest.class)
public interface ImageAsyncApi {
/**
* @see ImageApi#list()
*/
@Named("image:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseImages.class)
@Transform(ParseImages.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
ListenableFuture<? extends PagedIterable<? extends Resource>> list();
/** @see ImageApi#list(PaginationOptions) */
@Named("image:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseImages.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
ListenableFuture<? extends PaginatedCollection<? extends Resource>> list(PaginationOptions options);
/**
* @see ImageApi#listInDetail()
*/
@Named("image:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images/detail")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseImageDetails.class)
@Transform(ParseImageDetails.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
ListenableFuture<? extends PagedIterable<? extends Image>> listInDetail();
/** @see ImageApi#listInDetail(PaginationOptions) */
@Named("image:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images/detail")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseImageDetails.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
ListenableFuture<? extends PaginatedCollection<? extends Image>> listInDetail(PaginationOptions options);
/**
* @see ImageApi#get
*/
@Named("image:get")
@GET
@SelectJson("image")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images/{id}")
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends Image> get(@PathParam("id") String id);
/**
* @see ImageApi#delete
*/
@Named("image:delete")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images/{id}")
@Fallback(VoidOnNotFoundOr404.class)
ListenableFuture<Void> delete(@PathParam("id") String id);
/**
* @see ImageApi#getMetadata
*/
@Named("image:getmetadata")
@GET
@SelectJson("metadata")
@Path("/images/{id}/metadata")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyMapOnNotFoundOr404.class)
ListenableFuture<Map<String, String>> getMetadata(@PathParam("id") String id);
/**
* @see ImageApi#setMetadata
*/
@Named("image:setmetadata")
@PUT
@SelectJson("metadata")
@Path("/images/{id}/metadata")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Fallback(EmptyMapOnNotFoundOr404.class)
@MapBinder(BindToJsonPayload.class)
ListenableFuture<Map<String, String>> setMetadata(@PathParam("id") String id, @PayloadParam("metadata") Map<String, String> metadata);
/**
* @see ImageApi#updateMetadata
*/
@Named("image:updatemetadata")
@POST
@SelectJson("metadata")
@Path("/images/{id}/metadata")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Fallback(EmptyMapOnNotFoundOr404.class)
@MapBinder(BindToJsonPayload.class)
ListenableFuture<? extends Map<String, String>> updateMetadata(@PathParam("id") String id, @PayloadParam("metadata") Map<String, String> metadata);
/**
* @see ImageApi#getMetadata
*/
@Named("image:getmetadata")
@GET
@Path("/images/{id}/metadata/{key}")
@Consumes(MediaType.APPLICATION_JSON)
@ResponseParser(OnlyMetadataValueOrNull.class)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<String> getMetadata(@PathParam("id") String id, @PathParam("key") String key);
/**
* @see ImageApi#updateMetadata
*/
@Named("image:updatemetadata")
@PUT
@Path("/images/{id}/metadata/{key}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@ResponseParser(OnlyMetadataValueOrNull.class)
@MapBinder(BindMetadataToJsonPayload.class)
ListenableFuture<String> updateMetadata(@PathParam("id") String id,
@PathParam("key") @PayloadParam("key") String key, @PathParam("value") @PayloadParam("value") String value);
/**
* @see ImageApi#deleteMetadata
*/
@Named("image:deletemetadata")
@DELETE
@Consumes
@Path("/images/{id}/metadata/{key}")
@Fallback(VoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteMetadata(@PathParam("id") String id, @PathParam("key") String key);
}

View File

@ -17,46 +17,100 @@
package org.jclouds.openstack.nova.v2_0.features; package org.jclouds.openstack.nova.v2_0.features;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import java.util.Map; import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.AbsentOn403Or404Or500;
import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.collect.PagedIterable; import org.jclouds.collect.PagedIterable;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection; import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindMetadataToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.RebootType; import org.jclouds.openstack.nova.v2_0.domain.RebootType;
import org.jclouds.openstack.nova.v2_0.domain.Server; import org.jclouds.openstack.nova.v2_0.domain.Server;
import org.jclouds.openstack.nova.v2_0.domain.ServerCreated; import org.jclouds.openstack.nova.v2_0.domain.ServerCreated;
import org.jclouds.openstack.nova.v2_0.functions.ParseImageIdFromLocationHeader;
import org.jclouds.openstack.nova.v2_0.functions.internal.OnlyMetadataValueOrNull;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseDiagnostics;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseServerDetails;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseServers;
import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions; import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions;
import org.jclouds.openstack.nova.v2_0.options.RebuildServerOptions; import org.jclouds.openstack.nova.v2_0.options.RebuildServerOptions;
import org.jclouds.openstack.v2_0.domain.Resource; import org.jclouds.openstack.v2_0.domain.Resource;
import org.jclouds.openstack.v2_0.options.PaginationOptions; import org.jclouds.openstack.v2_0.options.PaginationOptions;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.binders.BindToJsonPayload;
/** /**
* Provides synchronous access to Server. * Provides access to the OpenStack Compute (Nova) Server API.
* <p/>
*
* @see ServerAsyncApi
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/1.1/content/Servers-d1e2073.html"
* />
*/ */
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
public interface ServerApi { public interface ServerApi {
/** /**
* List all servers (IDs, names, links) * List all servers (IDs, names, links)
* *
* @return all servers (IDs, names, links) * @return all servers (IDs, names, links)
*/ */
PagedIterable<? extends Resource> list(); @Named("server:list")
@GET
@ResponseParser(ParseServers.class)
@Transform(ParseServers.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Resource> list();
PaginatedCollection<? extends Resource> list(PaginationOptions options); @Named("server:list")
@GET
@ResponseParser(ParseServers.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
PaginatedCollection<Resource> list(PaginationOptions options);
/** /**
* List all servers (all details) * List all servers (all details)
* *
* @return all servers (all details) * @return all servers (all details)
*/ */
PagedIterable<? extends Server> listInDetail(); @Named("server:list")
@GET
@Path("/detail")
@ResponseParser(ParseServerDetails.class)
@Transform(ParseServerDetails.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Server> listInDetail();
PaginatedCollection<? extends Server> listInDetail(PaginationOptions options); @Named("server:list")
@GET
@Path("/detail")
@ResponseParser(ParseServerDetails.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
PaginatedCollection<Server> listInDetail(PaginationOptions options);
/** /**
* List details of the specified server * List details of the specified server
@ -65,7 +119,13 @@ public interface ServerApi {
* id of the server * id of the server
* @return server or null if not found * @return server or null if not found
*/ */
Server get(String id); @Named("server:get")
@GET
@Path("/{id}")
@SelectJson("server")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Server get(@PathParam("id") String id);
/** /**
* Create a new server * Create a new server
@ -81,7 +141,12 @@ public interface ServerApi {
* request * request
* @return the newly created server * @return the newly created server
*/ */
ServerCreated create(String name, String imageRef, String flavorRef, CreateServerOptions... options); @Named("server:create")
@POST
@Unwrap
@MapBinder(CreateServerOptions.class)
ServerCreated create(@PayloadParam("name") String name, @PayloadParam("imageRef") String imageRef,
@PayloadParam("flavorRef") String flavorRef, CreateServerOptions... options);
/** /**
* Terminate and delete a server. * Terminate and delete a server.
@ -90,7 +155,11 @@ public interface ServerApi {
* id of the server * id of the server
* @return True if successful, False otherwise * @return True if successful, False otherwise
*/ */
boolean delete(String id); @Named("server:delete")
@DELETE
@Path("/{id}")
@Fallback(FalseOnNotFoundOr404.class)
boolean delete(@PathParam("id") String id);
/** /**
* Start a server * Start a server
@ -98,7 +167,12 @@ public interface ServerApi {
* @param id * @param id
* id of the server * id of the server
*/ */
void start(String id); @Named("server:start")
@POST
@Path("/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"os-start\":null}")
void start(@PathParam("id") String id);
/** /**
* Stop a server * Stop a server
@ -106,7 +180,12 @@ public interface ServerApi {
* @param id * @param id
* id of the server * id of the server
*/ */
void stop(String id); @Named("server:stop")
@POST
@Path("/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"os-stop\":null}")
void stop(@PathParam("id") String id);
/** /**
* Reboot a server. * Reboot a server.
@ -116,7 +195,12 @@ public interface ServerApi {
* @param rebootType * @param rebootType
* The type of reboot to perform (Hard/Soft) * The type of reboot to perform (Hard/Soft)
*/ */
void reboot(String id, RebootType rebootType); @Named("server:reboot")
@POST
@Path("/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"reboot\":%7B\"type\":\"{type}\"%7D%7D")
void reboot(@PathParam("id") String id, @PayloadParam("type") RebootType rebootType);
/** /**
* Resize a server to a new flavor size. * Resize a server to a new flavor size.
@ -126,7 +210,12 @@ public interface ServerApi {
* @param flavorId * @param flavorId
* id of the new flavor to use * id of the new flavor to use
*/ */
void resize(String id, String flavorId); @Named("server:resize")
@POST
@Path("/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"resize\":%7B\"flavorRef\":{flavorId}%7D%7D")
void resize(@PathParam("id") String id, @PayloadParam("flavorId") String flavorId);
/** /**
* Confirm a resize operation. * Confirm a resize operation.
@ -134,7 +223,12 @@ public interface ServerApi {
* @param id * @param id
* id of the server * id of the server
*/ */
void confirmResize(String id); @Named("server:confirmResize")
@POST
@Path("/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"confirmResize\":null}")
void confirmResize(@PathParam("id") String id);
/** /**
* Revert a resize operation. * Revert a resize operation.
@ -142,7 +236,12 @@ public interface ServerApi {
* @param id * @param id
* id of the server * id of the server
*/ */
void revertResize(String id); @Named("server:revertResize")
@POST
@Path("/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"revertResize\":null}")
void revertResize(@PathParam("id") String id);
/** /**
* Rebuild a server. * Rebuild a server.
@ -152,7 +251,11 @@ public interface ServerApi {
* @param options * @param options
* Optional parameters to the rebuilding operation. * Optional parameters to the rebuilding operation.
*/ */
void rebuild(String id, RebuildServerOptions... options); @Named("server:rebuild")
@POST
@Path("/{id}/action")
@MapBinder(RebuildServerOptions.class)
void rebuild(@PathParam("id") String id, RebuildServerOptions... options);
/** /**
* Change the administrative password to a server. * Change the administrative password to a server.
@ -162,7 +265,12 @@ public interface ServerApi {
* @param adminPass * @param adminPass
* The new administrative password to use * The new administrative password to use
*/ */
void changeAdminPass(String id, String adminPass); @Named("server:changeAdminPass")
@POST
@Path("/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"changePassword\":%7B\"adminPass\":\"{adminPass}\"%7D%7D")
void changeAdminPass(@PathParam("id") String id, @PayloadParam("adminPass") String adminPass);
/** /**
* Rename a server. * Rename a server.
@ -172,7 +280,12 @@ public interface ServerApi {
* @param newName * @param newName
* The new name for the server * The new name for the server
*/ */
void rename(String id, String newName); @Named("server:rename")
@PUT
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"server\":%7B\"name\":\"{name}\"%7D%7D")
void rename(@PathParam("id") String id, @PayloadParam("name") String newName);
/** /**
* Create an image from a server. * Create an image from a server.
@ -184,7 +297,14 @@ public interface ServerApi {
* *
* @return ID of the new / updated image * @return ID of the new / updated image
*/ */
String createImageFromServer(String name, String id); @Named("server:createImageFromServer")
@POST
@Path("/{id}/action")
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"createImage\":%7B\"name\":\"{name}\", \"metadata\": %7B%7D%7D%7D")
@ResponseParser(ParseImageIdFromLocationHeader.class)
@Fallback(MapHttp4xxCodesToExceptions.class)
String createImageFromServer(@PayloadParam("name") String name, @PathParam("id") String id);
/** /**
* List all metadata for a server. * List all metadata for a server.
@ -194,7 +314,12 @@ public interface ServerApi {
* *
* @return the metadata as a Map<String, String> * @return the metadata as a Map<String, String>
*/ */
Map<String, String> getMetadata(String id); @Named("server:getMetadata")
@GET
@Path("/{id}/metadata")
@SelectJson("metadata")
@Fallback(EmptyMapOnNotFoundOr404.class)
Map<String, String> getMetadata(@PathParam("id") String id);
/** /**
* Set the metadata for a server. * Set the metadata for a server.
@ -205,7 +330,15 @@ public interface ServerApi {
* a Map containing the metadata * a Map containing the metadata
* @return the metadata as a Map<String, String> * @return the metadata as a Map<String, String>
*/ */
Map<String, String> setMetadata(String id, Map<String, String> metadata); @Named("server:setMetadata")
@PUT
@Path("/{id}/metadata")
@SelectJson("metadata")
@Produces(MediaType.APPLICATION_JSON)
@Fallback(EmptyMapOnNotFoundOr404.class)
@MapBinder(BindToJsonPayload.class)
Map<String, String> setMetadata(@PathParam("id") String id,
@PayloadParam("metadata") Map<String, String> metadata);
/** /**
* Update the metadata for a server. * Update the metadata for a server.
@ -216,7 +349,15 @@ public interface ServerApi {
* a Map containing the metadata * a Map containing the metadata
* @return the metadata as a Map<String, String> * @return the metadata as a Map<String, String>
*/ */
Map<String, String> updateMetadata(String id, Map<String, String> metadata); @Named("server:updateMetadata")
@POST
@Path("/{id}/metadata")
@Produces(MediaType.APPLICATION_JSON)
@SelectJson("metadata")
@MapBinder(BindToJsonPayload.class)
@Fallback(EmptyMapOnNotFoundOr404.class)
Map<String, String> updateMetadata(@PathParam("id") String id,
@PayloadParam("metadata") Map<String, String> metadata);
/** /**
* Update the metadata for a server. * Update the metadata for a server.
@ -227,8 +368,13 @@ public interface ServerApi {
* a Map containing the metadata * a Map containing the metadata
* @return the value or null if not present * @return the value or null if not present
*/ */
@Named("server:getMetadata")
@GET
@Path("/{id}/metadata/{key}")
@ResponseParser(OnlyMetadataValueOrNull.class)
@Fallback(NullOnNotFoundOr404.class)
@Nullable @Nullable
String getMetadata(String id, String key); String getMetadata(@PathParam("id") String id, @PathParam("key") String key);
/** /**
* Set a metadata item for a server. * Set a metadata item for a server.
@ -241,7 +387,14 @@ public interface ServerApi {
* the value of the metadata item * the value of the metadata item
* @return the value you updated * @return the value you updated
*/ */
String updateMetadata(String id, String key, String value); @Named("server:updateMetadata")
@PUT
@Path("/{id}/metadata/{key}")
@Produces(MediaType.APPLICATION_JSON)
@ResponseParser(OnlyMetadataValueOrNull.class)
@MapBinder(BindMetadataToJsonPayload.class)
String updateMetadata(@PathParam("id") String id, @PathParam("key") @PayloadParam("key") String key,
@PathParam("value") @PayloadParam("value") String value);
/** /**
* Delete a metadata item from a server. * Delete a metadata item from a server.
@ -251,8 +404,11 @@ public interface ServerApi {
* @param key * @param key
* the name of the metadata item * the name of the metadata item
*/ */
void deleteMetadata(String id, String key); @Named("server:deleteMetadata")
@DELETE
@Path("/{id}/metadata/{key}")
@Fallback(VoidOnNotFoundOr404.class)
void deleteMetadata(@PathParam("id") String id, @PathParam("key") String key);
/** /**
* Get usage information about the server such as CPU usage, Memory and IO. * Get usage information about the server such as CPU usage, Memory and IO.
@ -267,8 +423,11 @@ public interface ServerApi {
* @param id * @param id
* id of the server * id of the server
* @return A Map containing the collected values organized by key - value. * @return A Map containing the collected values organized by key - value.
* @Beta
*/ */
Optional<Map<String, String>> getDiagnostics(String id); @Named("server:getDiagnostics")
@GET
@Path("/{id}/diagnostics")
@ResponseParser(ParseDiagnostics.class)
@Fallback(AbsentOn403Or404Or500.class)
Optional<Map<String, String>> getDiagnostics(@PathParam("id") String id);
} }

View File

@ -1,355 +0,0 @@
/*
* 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.openstack.nova.v2_0.features;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.AbsentOn403Or404Or500;
import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindMetadataToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.RebootType;
import org.jclouds.openstack.nova.v2_0.domain.Server;
import org.jclouds.openstack.nova.v2_0.domain.ServerCreated;
import org.jclouds.openstack.nova.v2_0.functions.ParseImageIdFromLocationHeader;
import org.jclouds.openstack.nova.v2_0.functions.internal.OnlyMetadataValueOrNull;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseDiagnostics;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseServerDetails;
import org.jclouds.openstack.nova.v2_0.functions.internal.ParseServers;
import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions;
import org.jclouds.openstack.nova.v2_0.options.RebuildServerOptions;
import org.jclouds.openstack.v2_0.domain.Resource;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to Server via their REST API.
* <p/>
*
* @see ServerApi
* @see <a href= "http://docs.openstack.org/api/openstack-compute/1.1/content/Servers-d1e2073.html"
* />
*/
@RequestFilters(AuthenticateRequest.class)
public interface ServerAsyncApi {
/**
* @see ServerApi#list()
*/
@Named("server:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseServers.class)
@Transform(ParseServers.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
ListenableFuture<? extends PagedIterable<? extends Resource>> list();
/** @see ServerApi#list(PaginationOptions) */
@Named("server:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseServers.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
ListenableFuture<? extends PaginatedCollection<? extends Resource>> list(PaginationOptions options);
/**
* @see ServerApi#listInDetail()
*/
@Named("server:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/detail")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseServerDetails.class)
@Transform(ParseServerDetails.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
ListenableFuture<? extends PagedIterable<? extends Server>> listInDetail();
/** @see ServerApi#listInDetail(PaginationOptions) */
@Named("server:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/detail")
@RequestFilters(AuthenticateRequest.class)
@ResponseParser(ParseServerDetails.class)
@Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
ListenableFuture<? extends PaginatedCollection<? extends Server>> listInDetail(PaginationOptions options);
/**
* @see ServerApi#get
*/
@Named("server:get")
@GET
@SelectJson("server")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/{id}")
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<? extends Server> get(@PathParam("id") String id);
/**
* @see ServerApi#delete
*/
@Named("server:delete")
@DELETE
@Consumes
@Fallback(FalseOnNotFoundOr404.class)
@Path("/servers/{id}")
ListenableFuture<Boolean> delete(@PathParam("id") String id);
/**
* @see ServerApi#start
*/
@Named("server:start")
@POST
@Path("/servers/{id}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"os-start\":null}")
ListenableFuture<Void> start(@PathParam("id") String id);
/**
* @see ServerApi#stop
*/
@Named("server:stop")
@POST
@Path("/servers/{id}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"os-stop\":null}")
ListenableFuture<Void> stop(@PathParam("id") String id);
/**
* @see ServerApi#reboot
*/
@Named("server:reboot")
@POST
@Path("/servers/{id}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"reboot\":%7B\"type\":\"{type}\"%7D%7D")
ListenableFuture<Void> reboot(@PathParam("id") String id, @PayloadParam("type") RebootType rebootType);
/**
* @see ServerApi#resize
*/
@Named("server:resize")
@POST
@Path("/servers/{id}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"resize\":%7B\"flavorRef\":{flavorId}%7D%7D")
ListenableFuture<Void> resize(@PathParam("id") String id, @PayloadParam("flavorId") String flavorId);
/**
* @see ServerApi#confirmResize
*/
@Named("server:resize")
@POST
@Path("/servers/{id}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"confirmResize\":null}")
ListenableFuture<Void> confirmResize(@PathParam("id") String id);
/**
* @see ServerApi#revertResize
*/
@Named("server:resize")
@POST
@Path("/servers/{id}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("{\"revertResize\":null}")
ListenableFuture<Void> revertResize(@PathParam("id") String id);
/**
* @see ServerApi#create
*/
@Named("server:create")
@POST
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
@MapBinder(CreateServerOptions.class)
ListenableFuture<ServerCreated> create(@PayloadParam("name") String name, @PayloadParam("imageRef") String imageRef,
@PayloadParam("flavorRef") String flavorRef, CreateServerOptions... options);
/**
* @see ServerApi#rebuild
*/
@Named("server:rebuild")
@POST
@Path("/servers/{id}/action")
@Consumes
@MapBinder(RebuildServerOptions.class)
ListenableFuture<Void> rebuild(@PathParam("id") String id, RebuildServerOptions... options);
/**
* @see ServerApi#changeAdminPass
*/
@Named("server:changeadminpass")
@POST
@Path("/servers/{id}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"changePassword\":%7B\"adminPass\":\"{adminPass}\"%7D%7D")
ListenableFuture<Void> changeAdminPass(@PathParam("id") String id, @PayloadParam("adminPass") String adminPass);
/**
* @see ServerApi#rename
*/
@Named("server:rename")
@PUT
@Path("/servers/{id}")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"server\":%7B\"name\":\"{name}\"%7D%7D")
ListenableFuture<Void> rename(@PathParam("id") String id, @PayloadParam("name") String newName);
/**
* @see ServerApi#createImageFromServer
*/
@Named("server:create")
@POST
@Path("/servers/{id}/action")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"createImage\":%7B\"name\":\"{name}\", \"metadata\": %7B%7D%7D%7D")
@Fallback(MapHttp4xxCodesToExceptions.class)
@ResponseParser(ParseImageIdFromLocationHeader.class)
ListenableFuture<String> createImageFromServer(@PayloadParam("name") String name, @PathParam("id") String id);
/**
* @see ServerApi#getMetadata
*/
@Named("server:getmetadata")
@GET
@SelectJson("metadata")
@Path("/servers/{id}/metadata")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyMapOnNotFoundOr404.class)
ListenableFuture<? extends Map<String, String>> getMetadata(@PathParam("id") String id);
/**
* @see ServerApi#setMetadata
*/
@Named("server:setmetadata")
@PUT
@SelectJson("metadata")
@Path("/servers/{id}/metadata")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Fallback(EmptyMapOnNotFoundOr404.class)
@MapBinder(BindToJsonPayload.class)
ListenableFuture<? extends Map<String, String>> setMetadata(@PathParam("id") String id,
@PayloadParam("metadata") Map<String, String> metadata);
/**
* @see ServerApi#updateMetadata
*/
@Named("server:updatemetadata")
@POST
@SelectJson("metadata")
@Path("/servers/{id}/metadata")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Fallback(EmptyMapOnNotFoundOr404.class)
@MapBinder(BindToJsonPayload.class)
ListenableFuture<? extends Map<String, String>> updateMetadata(@PathParam("id") String id,
@PayloadParam("metadata") Map<String, String> metadata);
/**
* @see ServerApi#getMetadata
*/
@Named("server:getmetadata")
@GET
@Path("/servers/{id}/metadata/{key}")
@Consumes(MediaType.APPLICATION_JSON)
@ResponseParser(OnlyMetadataValueOrNull.class)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<String> getMetadata(@PathParam("id") String id, @PathParam("key") String key);
/**
* @see ServerApi#updateMetadata
*/
@Named("server:updatemetadata")
@PUT
@Path("/servers/{id}/metadata/{key}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@ResponseParser(OnlyMetadataValueOrNull.class)
@MapBinder(BindMetadataToJsonPayload.class)
ListenableFuture<String> updateMetadata(@PathParam("id") String id,
@PathParam("key") @PayloadParam("key") String key, @PathParam("value") @PayloadParam("value") String value);
/**
* @see ServerApi#deleteMetadata
*/
@Named("server:deletemetadata")
@DELETE
@Consumes
@Path("/servers/{id}/metadata/{key}")
@Fallback(VoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteMetadata(@PathParam("id") String id, @PathParam("key") String key);
/**
* @see ServerApi#getDiagnostics
*/
@Named("server:getdiagnostics")
@GET
@Path("/servers/{id}/diagnostics")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(AbsentOn403Or404Or500.class)
@ResponseParser(ParseDiagnostics.class)
ListenableFuture<Optional<Map<String, String>>> getDiagnostics(@PathParam("id") String id);
}

View File

@ -349,6 +349,7 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
.builder() .builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/71752/action") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/71752/action")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType( .payload(payloadFromStringWithContentType(
"{\"suspend\":null}", "application/json")) "{\"suspend\":null}", "application/json"))

View File

@ -94,7 +94,7 @@ public class AllocateAndAddFloatingIpToNodeExpectTest extends BaseNovaComputeSer
HttpRequest addFloatingIPRequest = HttpRequest.builder().method("POST").endpoint( HttpRequest addFloatingIPRequest = HttpRequest.builder().method("POST").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/71592/action")) URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/71592/action"))
.headers( .headers(
ImmutableMultimap.<String, String> builder().put("Accept", "*/*") ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).payload( .put("X-Auth-Token", authToken).build()).payload(
payloadFromStringWithContentType("{\"addFloatingIp\":{\"address\":\"" + address + "\"}}", payloadFromStringWithContentType("{\"addFloatingIp\":{\"address\":\"" + address + "\"}}",
"application/json")).build(); "application/json")).build();

View File

@ -341,6 +341,7 @@ public class AdminActionsApiExpectTest extends BaseNovaApiExpectTest {
return HttpRequest.builder() return HttpRequest.builder()
.method("POST") .method("POST")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.addHeader("Accept", "application/json")
.payload(payloadFromStringWithContentType("{\"" + actionName + "\":null}", MediaType.APPLICATION_JSON)) .payload(payloadFromStringWithContentType("{\"" + actionName + "\":null}", MediaType.APPLICATION_JSON))
.endpoint(endpoint); .endpoint(endpoint);
} }

View File

@ -92,7 +92,6 @@ public class ConsolesApiMockTest extends BaseOpenStackMockTest<NovaApi> {
String zoneId = getFirst(novaApi.getConfiguredZones(), "RegionTwo"); String zoneId = getFirst(novaApi.getConfiguredZones(), "RegionTwo");
System.out.println("zoneId: " + zoneId);
ConsolesApi consolesApi = novaApi.getConsolesExtensionForZone(zoneId).get(); ConsolesApi consolesApi = novaApi.getConsolesExtensionForZone(zoneId).get();
assertEquals(server.getRequestCount(), 2); assertEquals(server.getRequestCount(), 2);

View File

@ -32,7 +32,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
/** /**
* Tests annotation parsing of {@code FloatingIPAsyncApi} * Tests annotation parsing of {@code FloatingIPApi}
*/ */
@Test(groups = "unit", testName = "FloatingIPApiExpectTest") @Test(groups = "unit", testName = "FloatingIPApiExpectTest")
public class FloatingIPApiExpectTest extends BaseNovaApiExpectTest { public class FloatingIPApiExpectTest extends BaseNovaApiExpectTest {

View File

@ -31,7 +31,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
/** /**
* Tests annotation parsing of {@code KeyPairAsyncApi} * Tests annotation parsing of {@code KeyPairApi}
*/ */
@Test(groups = "unit", testName = "KeyPairApiExpectTest") @Test(groups = "unit", testName = "KeyPairApiExpectTest")
public class KeyPairApiExpectTest extends BaseNovaApiExpectTest { public class KeyPairApiExpectTest extends BaseNovaApiExpectTest {
@ -128,7 +128,7 @@ public class KeyPairApiExpectTest extends BaseNovaApiExpectTest {
.builder() .builder()
.method("DELETE") .method("DELETE")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-keypairs/testkeypair") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-keypairs/testkeypair")
.addHeader("Accept", "*/*") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(202).build(); HttpResponse deleteResponse = HttpResponse.builder().statusCode(202).build();

View File

@ -82,6 +82,7 @@ public class QuotaApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().endpoint(endpoint).method("PUT") HttpRequest.builder().endpoint(endpoint).method("PUT")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.addHeader("Accept", "application/json")
.payload(payloadFromResourceWithContentType("/quotas.json", MediaType.APPLICATION_JSON)) .payload(payloadFromResourceWithContentType("/quotas.json", MediaType.APPLICATION_JSON))
.build(), .build(),
HttpResponse.builder().statusCode(200).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get(); HttpResponse.builder().statusCode(200).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get();
@ -96,6 +97,7 @@ public class QuotaApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().endpoint(endpoint).method("PUT") HttpRequest.builder().endpoint(endpoint).method("PUT")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.addHeader("Accept", "application/json")
.payload(payloadFromResourceWithContentType("/quotas.json", MediaType.APPLICATION_JSON)) .payload(payloadFromResourceWithContentType("/quotas.json", MediaType.APPLICATION_JSON))
.build(), .build(),
HttpResponse.builder().statusCode(404).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get(); HttpResponse.builder().statusCode(404).build()).getQuotaExtensionForZone("az-1.region-a.geo-1").get();

View File

@ -38,7 +38,7 @@ import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
/** /**
* Tests annotation parsing of {@code SecurityGroupAsyncApi} * Tests annotation parsing of {@code SecurityGroupApi}
*/ */
@Test(groups = "unit", testName = "SecurityGroupApiExpectTest") @Test(groups = "unit", testName = "SecurityGroupApiExpectTest")
public class SecurityGroupApiExpectTest extends BaseNovaApiExpectTest { public class SecurityGroupApiExpectTest extends BaseNovaApiExpectTest {
@ -206,7 +206,7 @@ public class SecurityGroupApiExpectTest extends BaseNovaApiExpectTest {
HttpRequest deleteRule = HttpRequest.builder().method("DELETE").endpoint( HttpRequest deleteRule = HttpRequest.builder().method("DELETE").endpoint(
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-group-rules/161")) URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-security-group-rules/161"))
.headers( .headers(
ImmutableMultimap.<String, String> builder().put("Accept", "*/*") ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build(); .put("X-Auth-Token", authToken).build()).build();
HttpResponse deleteRuleResponse = HttpResponse.builder().statusCode(202).build(); HttpResponse deleteRuleResponse = HttpResponse.builder().statusCode(202).build();

View File

@ -31,18 +31,18 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
/** /**
* Tests annotation parsing of {@code ExtensionAsyncApi} * Tests annotation parsing of {@code ExtensionApi}
*/ */
@Test(groups = "unit", testName = "ExtensionApiExpectTest") @Test(groups = "unit", testName = "ExtensionApiExpectTest")
public class ExtensionApiExpectTest extends BaseNovaApiExpectTest { public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
public void testListExtensionsWhenResponseIs2xx() throws Exception { public void testListExtensionsWhenResponseIs2xx() throws Exception {
HttpRequest listExtensions = HttpRequest HttpRequest listExtensions = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listExtensionsResponse = HttpResponse.builder().statusCode(200) HttpResponse listExtensionsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/extension_list.json")).build(); .payload(payloadFromResource("/extension_list.json")).build();
@ -57,12 +57,12 @@ public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testListExtensionsWhenReponseIs404IsEmpty() throws Exception { public void testListExtensionsWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listExtensions = HttpRequest HttpRequest listExtensions = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listExtensionsResponse = HttpResponse.builder().statusCode(404).build(); HttpResponse listExtensionsResponse = HttpResponse.builder().statusCode(404).build();
@ -74,13 +74,12 @@ public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
// TODO: gson deserializer for Multimap // TODO: gson deserializer for Multimap
public void testGetExtensionByAliasWhenResponseIs2xx() throws Exception { public void testGetExtensionByAliasWhenResponseIs2xx() throws Exception {
HttpRequest getExtension = HttpRequest.builder()
HttpRequest getExtension = HttpRequest
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions/RS-PIE") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions/RS-PIE")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getExtensionResponse = HttpResponse.builder().statusCode(200) HttpResponse getExtensionResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/extension_details.json")).build(); .payload(payloadFromResource("/extension_details.json")).build();
@ -93,12 +92,12 @@ public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testGetExtensionByAliasWhenResponseIs404() throws Exception { public void testGetExtensionByAliasWhenResponseIs404() throws Exception {
HttpRequest getExtension = HttpRequest HttpRequest getExtension = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions/RS-PIE") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions/RS-PIE")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getExtensionResponse = HttpResponse.builder().statusCode(404) HttpResponse getExtensionResponse = HttpResponse.builder().statusCode(404)
.payload(payloadFromResource("/extension_details.json")).build(); .payload(payloadFromResource("/extension_details.json")).build();
@ -107,7 +106,5 @@ public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, getExtension, getExtensionResponse); responseWithKeystoneAccess, getExtension, getExtensionResponse);
assertNull(apiWhenNoExtensionsExist.getExtensionApiForZone("az-1.region-a.geo-1").get("RS-PIE")); assertNull(apiWhenNoExtensionsExist.getExtensionApiForZone("az-1.region-a.geo-1").get("RS-PIE"));
} }
} }

View File

@ -37,18 +37,18 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.net.HttpHeaders; import com.google.common.net.HttpHeaders;
/** /**
* Tests annotation parsing of {@code FlavorAsyncApi} * Tests annotation parsing of {@code FlavorApi}
*/ */
@Test(groups = "unit", testName = "FlavorApiExpectTest") @Test(groups = "unit", testName = "FlavorApiExpectTest")
public class FlavorApiExpectTest extends BaseNovaApiExpectTest { public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
public void testListFlavorsWhenResponseIs2xx() throws Exception { public void testListFlavorsWhenResponseIs2xx() throws Exception {
HttpRequest listFlavors = HttpRequest HttpRequest listFlavors = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listFlavorsResponse = HttpResponse.builder().statusCode(200) HttpResponse listFlavorsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/flavor_list.json")).build(); .payload(payloadFromResource("/flavor_list.json")).build();
@ -63,12 +63,12 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testListFlavorsWhenReponseIs404IsEmpty() throws Exception { public void testListFlavorsWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listFlavors = HttpRequest HttpRequest listFlavors = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listFlavorsResponse = HttpResponse.builder().statusCode(404).build(); HttpResponse listFlavorsResponse = HttpResponse.builder().statusCode(404).build();
@ -80,13 +80,12 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
// TODO: gson deserializer for Multimap // TODO: gson deserializer for Multimap
public void testGetFlavorWhenResponseIs2xx() throws Exception { public void testGetFlavorWhenResponseIs2xx() throws Exception {
HttpRequest getFlavor = HttpRequest.builder()
HttpRequest getFlavor = HttpRequest
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors/52415800-8b69-11e0-9b19-734f1195ff37") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors/52415800-8b69-11e0-9b19-734f1195ff37")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getFlavorResponse = HttpResponse.builder().statusCode(200) HttpResponse getFlavorResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/flavor_details.json")).build(); .payload(payloadFromResource("/flavor_details.json")).build();
@ -100,8 +99,7 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testGetFlavorWhenResponseIs404() throws Exception { public void testGetFlavorWhenResponseIs404() throws Exception {
HttpRequest getFlavor = HttpRequest HttpRequest getFlavor = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors/123") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors/123")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -114,13 +112,11 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, getFlavor, getFlavorResponse); responseWithKeystoneAccess, getFlavor, getFlavorResponse);
assertNull(apiWhenNoFlavorsExist.getFlavorApiForZone("az-1.region-a.geo-1").get("123")); assertNull(apiWhenNoFlavorsExist.getFlavorApiForZone("az-1.region-a.geo-1").get("123"));
} }
public void testCreateFlavor200() throws Exception { public void testCreateFlavor200() throws Exception {
ParseCreateFlavorTest parser = new ParseCreateFlavorTest(); ParseCreateFlavorTest parser = new ParseCreateFlavorTest();
HttpRequest listFlavors = HttpRequest HttpRequest listFlavors = HttpRequest.builder()
.builder()
.method(HttpMethod.POST) .method(HttpMethod.POST)
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors")
.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON) .addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)
@ -143,12 +139,10 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
public void testDeleteFlavor202() throws Exception { public void testDeleteFlavor202() throws Exception {
String flavorId = "1cb47a44-9b84-4da4-bf81-c1976e8414ab"; String flavorId = "1cb47a44-9b84-4da4-bf81-c1976e8414ab";
HttpRequest updateMetadata = HttpRequest.builder()
HttpRequest updateMetadata = HttpRequest
.builder()
.method(HttpMethod.DELETE) .method(HttpMethod.DELETE)
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors/" + flavorId) .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors/" + flavorId)
.addHeader(HttpHeaders.ACCEPT, MediaType.WILDCARD) .addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.build(); .build();

View File

@ -35,17 +35,18 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
/** /**
* Tests annotation parsing of {@code ImageAsyncApi} * Tests annotation parsing of {@code ImageApi}
*/ */
@Test(groups = "unit", testName = "ImageAsyncApiTest") @Test(groups = "unit", testName = "ImageApiExpectTest")
public class ImageApiExpectTest extends BaseNovaApiExpectTest { public class ImageApiExpectTest extends BaseNovaApiExpectTest {
public void testListImagesWhenResponseIs2xx() throws Exception { public void testListImagesWhenResponseIs2xx() throws Exception {
HttpRequest list = HttpRequest HttpRequest list = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listResponse = HttpResponse.builder().statusCode(200) HttpResponse listResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_list.json")).build(); .payload(payloadFromResource("/image_list.json")).build();
@ -60,12 +61,12 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testListImagesWhenReponseIs404IsEmpty() throws Exception { public void testListImagesWhenReponseIs404IsEmpty() throws Exception {
HttpRequest list = HttpRequest HttpRequest list = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listResponse = HttpResponse.builder().statusCode(404).build(); HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
@ -77,12 +78,12 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
public void testGetImageWhenResponseIs2xx() throws Exception { public void testGetImageWhenResponseIs2xx() throws Exception {
HttpRequest getImage = HttpRequest HttpRequest getImage = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/52415800-8b69-11e0-9b19-734f5736d2a2") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/52415800-8b69-11e0-9b19-734f5736d2a2")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getImageResponse = HttpResponse.builder().statusCode(200) HttpResponse getImageResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_details.json")).build(); .payload(payloadFromResource("/image_details.json")).build();
@ -96,31 +97,29 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testGetImageWhenResponseIs404() throws Exception { public void testGetImageWhenResponseIs404() throws Exception {
HttpRequest getImage = HttpRequest HttpRequest getImage = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/52415800-8b69-11e0-9b19-734f5736d2a2") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/52415800-8b69-11e0-9b19-734f5736d2a2")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getImageResponse = HttpResponse.builder().statusCode(404).build(); HttpResponse getImageResponse = HttpResponse.builder().statusCode(404).build();
NovaApi apiWhenNoImagesExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, NovaApi apiWhenNoImagesExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, getImage, getImageResponse); responseWithKeystoneAccess, getImage, getImageResponse);
assertNull(apiWhenNoImagesExist.getImageApiForZone("az-1.region-a.geo-1").get( assertNull(apiWhenNoImagesExist.getImageApiForZone("az-1.region-a.geo-1").get("52415800-8b69-11e0-9b19-734f5736d2a2"));
"52415800-8b69-11e0-9b19-734f5736d2a2"));
} }
public void testListMetadataWhenResponseIs2xx() throws Exception { public void testListMetadataWhenResponseIs2xx() throws Exception {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2"; String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
HttpRequest getMetadata = HttpRequest HttpRequest getMetadata = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getMetadataResponse = HttpResponse.builder().statusCode(200) HttpResponse getMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_list.json")).build(); .payload(payloadFromResource("/metadata_list.json")).build();
@ -134,8 +133,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
public void testListMetadataWhenResponseIs404() throws Exception { public void testListMetadataWhenResponseIs404() throws Exception {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2"; String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
HttpRequest getMetadata = HttpRequest HttpRequest getMetadata = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "*/*") .addHeader("Accept", "*/*")
@ -162,13 +160,13 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
.put("Image Version", "2.1") .put("Image Version", "2.1")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("PUT") .method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 1\",\"Image Version\":\"2.1\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 1\",\"Image Version\":\"2.1\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200) HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
@ -188,13 +186,13 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
.put("Image Version", "2.1") .put("Image Version", "2.1")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("PUT") .method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "*/*") .addHeader("Accept", "*/*")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 1\",\"Image Version\":\"2.1\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 1\",\"Image Version\":\"2.1\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404).build(); HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404).build();
@ -217,13 +215,13 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server") .put("Server Description", "Simple Server")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200) HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
@ -243,8 +241,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server") .put("Server Description", "Simple Server")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + imageId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + imageId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -270,8 +267,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2"; String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image%20Version"; String key = "Image%20Version";
HttpRequest getMetadata = HttpRequest HttpRequest getMetadata = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key) .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key)
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -292,8 +288,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2"; String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image%20Version"; String key = "Image%20Version";
HttpRequest getMetadata = HttpRequest HttpRequest getMetadata = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key) .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key)
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -313,8 +308,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2"; String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image Version"; String key = "Image Version";
HttpRequest updateMetadata = HttpRequest HttpRequest updateMetadata = HttpRequest.builder()
.builder()
.method("PUT") .method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + "Image%20Version") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + "Image%20Version")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -336,11 +330,10 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2"; String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image%20Version"; String key = "Image%20Version";
HttpRequest deleteMetadata = HttpRequest HttpRequest deleteMetadata = HttpRequest.builder()
.builder()
.method("DELETE") .method("DELETE")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key) .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key)
.addHeader("Accept", "*/*") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.build(); .build();
@ -356,11 +349,10 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2"; String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image%20Version"; String key = "Image%20Version";
HttpRequest deleteMetadata = HttpRequest HttpRequest deleteMetadata = HttpRequest.builder()
.builder()
.method("DELETE") .method("DELETE")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key) .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key)
.addHeader("Accept", "*/*") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.build(); .build();
@ -370,6 +362,5 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, deleteMetadata, deleteMetadataResponse); responseWithKeystoneAccess, deleteMetadata, deleteMetadataResponse);
apiWhenImageExists.getImageApiForZone("az-1.region-a.geo-1").deleteMetadata(imageId, key); apiWhenImageExists.getImageApiForZone("az-1.region-a.geo-1").deleteMetadata(imageId, key);
} }
} }

View File

@ -31,23 +31,22 @@ import org.jclouds.openstack.nova.v2_0.parse.ParseCreatedServerTest;
import org.jclouds.openstack.nova.v2_0.parse.ParseMetadataListTest; import org.jclouds.openstack.nova.v2_0.parse.ParseMetadataListTest;
import org.jclouds.openstack.nova.v2_0.parse.ParseMetadataUpdateTest; import org.jclouds.openstack.nova.v2_0.parse.ParseMetadataUpdateTest;
import org.jclouds.openstack.nova.v2_0.parse.ParseServerDetailsStatesTest; import org.jclouds.openstack.nova.v2_0.parse.ParseServerDetailsStatesTest;
import org.jclouds.openstack.nova.v2_0.parse.ParseServerDiagnostics;
import org.jclouds.openstack.nova.v2_0.parse.ParseServerListTest; import org.jclouds.openstack.nova.v2_0.parse.ParseServerListTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import org.jclouds.openstack.nova.v2_0.parse.ParseServerDiagnostics;
/** /**
* Tests annotation parsing of {@code ServerAsyncApi} * Tests annotation parsing of {@code ServerApi}
*/ */
@Test(groups = "unit", testName = "ServerAsyncApiTest") @Test(groups = "unit", testName = "ServerApiExpectTest")
public class ServerApiExpectTest extends BaseNovaApiExpectTest { public class ServerApiExpectTest extends BaseNovaApiExpectTest {
public void testListServersWhenResponseIs2xx() throws Exception { public void testListServersWhenResponseIs2xx() throws Exception {
HttpRequest listServers = HttpRequest HttpRequest listServers = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -66,8 +65,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testListServersWhenReponseIs404IsEmpty() throws Exception { public void testListServersWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listServers = HttpRequest HttpRequest listServers = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -118,8 +116,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testCreateServerWhenResponseIs202() throws Exception { public void testCreateServerWhenResponseIs202() throws Exception {
HttpRequest createServer = HttpRequest HttpRequest createServer = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -128,7 +125,6 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\"}}", "application/json")) "{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\"}}", "application/json"))
.build(); .build();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted") HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_server.json", "application/json; charset=UTF-8")).build(); .payload(payloadFromResourceWithContentType("/new_server.json", "application/json; charset=UTF-8")).build();
@ -140,8 +136,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testCreateServerInAvailabilityZoneWhenResponseIs202() throws Exception { public void testCreateServerInAvailabilityZoneWhenResponseIs202() throws Exception {
HttpRequest createServer = HttpRequest HttpRequest createServer = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -150,7 +145,6 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"availability_zone\":\"nova\"}}", "application/json")) "{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"availability_zone\":\"nova\"}}", "application/json"))
.build(); .build();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted") HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_server_in_zone.json", "application/json; charset=UTF-8")).build(); .payload(payloadFromResourceWithContentType("/new_server_in_zone.json", "application/json; charset=UTF-8")).build();
@ -164,9 +158,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testCreateServerWithSecurityGroupsWhenResponseIs202() throws Exception { public void testCreateServerWithSecurityGroupsWhenResponseIs202() throws Exception {
HttpRequest createServer = HttpRequest.builder()
HttpRequest createServer = HttpRequest
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -175,11 +167,9 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"security_groups\":[{\"name\":\"group1\"},{\"name\":\"group2\"}]}}", "application/json")) "{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"security_groups\":[{\"name\":\"group1\"},{\"name\":\"group2\"}]}}", "application/json"))
.build(); .build();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted") HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_server.json", "application/json; charset=UTF-8")).build(); .payload(payloadFromResourceWithContentType("/new_server.json", "application/json; charset=UTF-8")).build();
NovaApi apiWithNewServer = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, NovaApi apiWithNewServer = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, createServer, createServerResponse); responseWithKeystoneAccess, createServer, createServerResponse);
@ -189,9 +179,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testCreateServerWithNetworksWhenResponseIs202() throws Exception { public void testCreateServerWithNetworksWhenResponseIs202() throws Exception {
HttpRequest createServer = HttpRequest.builder()
HttpRequest createServer = HttpRequest
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -200,11 +188,9 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"networks\":[{\"uuid\":\"b3856ac0-f481-11e2-b778-0800200c9a66\"},{\"uuid\":\"bf0f0f90-f481-11e2-b778-0800200c9a66\"}]}}", "application/json")) "{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"networks\":[{\"uuid\":\"b3856ac0-f481-11e2-b778-0800200c9a66\"},{\"uuid\":\"bf0f0f90-f481-11e2-b778-0800200c9a66\"}]}}", "application/json"))
.build(); .build();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted") HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_server.json", "application/json; charset=UTF-8")).build(); .payload(payloadFromResourceWithContentType("/new_server.json", "application/json; charset=UTF-8")).build();
NovaApi apiWithNewServer = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, NovaApi apiWithNewServer = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, createServer, createServerResponse); responseWithKeystoneAccess, createServer, createServerResponse);
@ -214,9 +200,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testCreateServerWithDiskConfigAuto() throws Exception { public void testCreateServerWithDiskConfigAuto() throws Exception {
HttpRequest createServer = HttpRequest.builder()
HttpRequest createServer = HttpRequest
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -225,11 +209,9 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"OS-DCF:diskConfig\":\"AUTO\"}}", "application/json")) "{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"OS-DCF:diskConfig\":\"AUTO\"}}", "application/json"))
.build(); .build();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted") HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_server_disk_config_auto.json", "application/json; charset=UTF-8")).build(); .payload(payloadFromResourceWithContentType("/new_server_disk_config_auto.json", "application/json; charset=UTF-8")).build();
NovaApi apiWithNewServer = requestsSendResponses( NovaApi apiWithNewServer = requestsSendResponses(
keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess, keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess,
createServer, createServerResponse); createServer, createServerResponse);
@ -240,9 +222,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
} }
public void testCreateServerWithDiskConfigManual() throws Exception { public void testCreateServerWithDiskConfigManual() throws Exception {
HttpRequest createServer = HttpRequest.builder()
HttpRequest createServer = HttpRequest
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -251,11 +231,9 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"OS-DCF:diskConfig\":\"MANUAL\"}}", "application/json")) "{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"OS-DCF:diskConfig\":\"MANUAL\"}}", "application/json"))
.build(); .build();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted") HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_server_disk_config_manual.json", "application/json; charset=UTF-8")).build(); .payload(payloadFromResourceWithContentType("/new_server_disk_config_manual.json", "application/json; charset=UTF-8")).build();
NovaApi apiWithNewServer = requestsSendResponses( NovaApi apiWithNewServer = requestsSendResponses(
keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess, keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess,
createServer, createServerResponse); createServer, createServerResponse);
@ -267,11 +245,10 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
public void testRebuildServerWhenResponseIs202() throws Exception { public void testRebuildServerWhenResponseIs202() throws Exception {
String serverId = "52415800-8b69-11e0-9b19-734f565bc83b"; String serverId = "52415800-8b69-11e0-9b19-734f565bc83b";
HttpRequest rebuildServer = HttpRequest HttpRequest rebuildServer = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "*/*") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType( .payload(payloadFromStringWithContentType(
"{\"rebuild\":{\"adminPass\":\"password\",\"imageRef\":\"1234\",\"name\":\"newName\",\"accessIPv4\":\"1.1.1.1\",\"accessIPv6\":\"fe80::100\"}}", "application/json")) "{\"rebuild\":{\"adminPass\":\"password\",\"imageRef\":\"1234\",\"name\":\"newName\",\"accessIPv4\":\"1.1.1.1\",\"accessIPv6\":\"fe80::100\"}}", "application/json"))
@ -292,8 +269,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "456"; String imageId = "456";
String imageName = "foo"; String imageName = "foo";
HttpRequest createImage = HttpRequest HttpRequest createImage = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -304,8 +280,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
HttpResponse createImageResponse = HttpResponse.builder() HttpResponse createImageResponse = HttpResponse.builder()
.statusCode(200) .statusCode(200)
.headers( .headers(ImmutableMultimap.<String, String> builder()
ImmutableMultimap.<String, String> builder()
.put("Location", "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId).build()).build(); .put("Location", "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId).build()).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
@ -319,8 +294,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
String serverId = "123"; String serverId = "123";
String imageName = "foo"; String imageName = "foo";
HttpRequest createImage = HttpRequest HttpRequest createImage = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
@ -330,6 +304,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.build(); .build();
HttpResponse createImageResponse = HttpResponse.builder().statusCode(404).build(); HttpResponse createImageResponse = HttpResponse.builder().statusCode(404).build();
NovaApi apiWhenServerDoesNotExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, NovaApi apiWhenServerDoesNotExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, createImage, createImageResponse); responseWithKeystoneAccess, createImage, createImageResponse);
@ -343,11 +318,10 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
public void testStopServerWhenResponseIs2xx() throws Exception { public void testStopServerWhenResponseIs2xx() throws Exception {
String serverId = "123"; String serverId = "123";
HttpRequest stopServer = HttpRequest HttpRequest stopServer = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "*/*") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType( .payload(payloadFromStringWithContentType(
"{\"os-stop\":null}", "application/json")) "{\"os-stop\":null}", "application/json"))
@ -363,13 +337,11 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
public void testStopServerWhenResponseIs404() throws Exception { public void testStopServerWhenResponseIs404() throws Exception {
String serverId = "123"; String serverId = "123";
HttpRequest stopServer = HttpRequest HttpRequest stopServer = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "*/*") .addHeader("Accept", "*/*")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType( .payload(payloadFromStringWithContentType(
"{\"os-stop\":null}", "application/json")) "{\"os-stop\":null}", "application/json"))
.build(); .build();
@ -393,9 +365,8 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.builder() .builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "*/*") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType( .payload(payloadFromStringWithContentType(
"{\"os-start\":null}", "application/json")) "{\"os-start\":null}", "application/json"))
.build(); .build();
@ -410,14 +381,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
public void testStartServerWhenResponseIs404() throws Exception { public void testStartServerWhenResponseIs404() throws Exception {
String serverId = "123"; String serverId = "123";
HttpRequest startServer = HttpRequest HttpRequest startServer = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "*/*") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType( .payload(payloadFromStringWithContentType(
"{\"os-startp\":null}", "application/json")) "{\"os-start\":null}", "application/json"))
.build(); .build();
HttpResponse startServerResponse = HttpResponse.builder().statusCode(404).build(); HttpResponse startServerResponse = HttpResponse.builder().statusCode(404).build();
@ -435,18 +405,16 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
public void testListMetadataWhenResponseIs2xx() throws Exception { public void testListMetadataWhenResponseIs2xx() throws Exception {
String serverId = "123"; String serverId = "123";
HttpRequest getMetadata = HttpRequest.builder()
HttpRequest getMetadata = HttpRequest
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build(); .addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getMetadataResponse = HttpResponse.builder().statusCode(200) HttpResponse getMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_list.json")).build(); .payload(payloadFromResource("/metadata_list.json")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, getMetadata, getMetadataResponse); responseWithKeystoneAccess, getMetadata, getMetadataResponse);
@ -456,8 +424,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
public void testListMetadataWhenResponseIs404() throws Exception { public void testListMetadataWhenResponseIs404() throws Exception {
String serverId = "123"; String serverId = "123";
HttpRequest getMetadata = HttpRequest HttpRequest getMetadata = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "*/*") .addHeader("Accept", "*/*")
@ -484,13 +451,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Image Version", "2.1") .put("Image Version", "2.1")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("PUT") .method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 1\",\"Image Version\":\"2.1\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 1\",\"Image Version\":\"2.1\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200) HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
@ -510,13 +477,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Image Version", "2.1") .put("Image Version", "2.1")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("PUT") .method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "*/*") .addHeader("Accept", "*/*")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 1\",\"Image Version\":\"2.1\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 1\",\"Image Version\":\"2.1\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404).build(); HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404).build();
@ -539,13 +506,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server") .put("Server Description", "Simple Server")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200) HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
@ -565,13 +532,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server") .put("Server Description", "Simple Server")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "*/*")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404) HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404)
@ -616,13 +583,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Label", "Web Head 1") .put("Server Label", "Web Head 1")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404) HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404)
@ -646,13 +613,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server") .put("Server Description", "Simple Server")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200) HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
@ -672,13 +639,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server") .put("Server Description", "Simple Server")
.build(); .build();
HttpRequest setMetadata = HttpRequest HttpRequest setMetadata = HttpRequest.builder()
.builder()
.method("POST") .method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json")) .payload(payloadFromStringWithContentType(
"{\"metadata\":{\"Server Label\":\"Web Head 2\",\"Server Description\":\"Simple Server\"}}", "application/json"))
.build(); .build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404) HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404)
@ -699,11 +666,10 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
String serverId = "123"; String serverId = "123";
String key = "Server%20Label"; String key = "Server%20Label";
HttpRequest updateMetadata = HttpRequest HttpRequest updateMetadata = HttpRequest.builder()
.builder()
.method("DELETE") .method("DELETE")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata/" + key) .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata/" + key)
.addHeader("Accept", "*/*") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.build(); .build();
@ -713,18 +679,16 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, updateMetadata, updateMetadataResponse); responseWithKeystoneAccess, updateMetadata, updateMetadataResponse);
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").deleteMetadata(serverId, key); apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").deleteMetadata(serverId, key);
} }
public void testDeleteMetadataItemWhenResponseIs404() throws Exception { public void testDeleteMetadataItemWhenResponseIs404() throws Exception {
String serverId = "123"; String serverId = "123";
String key = "Server%20Label"; String key = "Server%20Label";
HttpRequest deleteMetadata = HttpRequest HttpRequest deleteMetadata = HttpRequest.builder()
.builder()
.method("DELETE") .method("DELETE")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata/" + key) .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata/" + key)
.addHeader("Accept", "*/*") .addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.build(); .build();
@ -734,21 +698,17 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, deleteMetadata, deleteMetadataResponse); responseWithKeystoneAccess, deleteMetadata, deleteMetadataResponse);
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").deleteMetadata(serverId, key); apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").deleteMetadata(serverId, key);
} }
public void testGetDiagnosticsWhenResponseIs200() throws Exception { public void testGetDiagnosticsWhenResponseIs200() throws Exception {
String serverId = "123"; String serverId = "123";
HttpRequest getDiagnostics = HttpRequest HttpRequest getDiagnostics = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/diagnostics") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/diagnostics")
.addHeader("X-Auth-Token", authToken) .addHeader("X-Auth-Token", authToken)
.build(); .build();
HttpResponse serverDiagnosticsResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted") HttpResponse serverDiagnosticsResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/server_diagnostics.json", "application/json; charset=UTF-8")).build(); .payload(payloadFromResourceWithContentType("/server_diagnostics.json", "application/json; charset=UTF-8")).build();
@ -758,12 +718,9 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
new ParseServerDiagnostics().expected()); new ParseServerDiagnostics().expected());
} }
public void testGetDiagnosticsWhenResponseIs403Or404Or500() throws Exception { public void testGetDiagnosticsWhenResponseIs403Or404Or500() throws Exception {
String serverId = "123"; String serverId = "123";
HttpRequest getDiagnostics = HttpRequest HttpRequest getDiagnostics = HttpRequest.builder()
.builder()
.method("GET") .method("GET")
.addHeader("Accept", "application/json") .addHeader("Accept", "application/json")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/diagnostics") .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/diagnostics")
@ -775,7 +732,4 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
HttpResponse.builder().statusCode(statusCode).build()).getServerApiForZone("az-1.region-a.geo-1").getDiagnostics(serverId).isPresent()); HttpResponse.builder().statusCode(statusCode).build()).getServerApiForZone("az-1.region-a.geo-1").getDiagnostics(serverId).isPresent());
} }
} }
} }

View File

@ -38,7 +38,6 @@ import org.jclouds.compute.config.ComputeServiceProperties;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.openstack.nova.v2_0.NovaApi; import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.openstack.nova.v2_0.NovaAsyncApi;
import org.jclouds.openstack.nova.v2_0.domain.Server; import org.jclouds.openstack.nova.v2_0.domain.Server;
import org.jclouds.openstack.nova.v2_0.features.ServerApi; import org.jclouds.openstack.nova.v2_0.features.ServerApi;
import org.jclouds.rackspace.clouddns.v1.domain.CreateDomain; import org.jclouds.rackspace.clouddns.v1.domain.CreateDomain;
@ -46,7 +45,6 @@ import org.jclouds.rackspace.clouddns.v1.domain.Domain;
import org.jclouds.rackspace.clouddns.v1.domain.Record; import org.jclouds.rackspace.clouddns.v1.domain.Record;
import org.jclouds.rackspace.clouddns.v1.domain.RecordDetail; import org.jclouds.rackspace.clouddns.v1.domain.RecordDetail;
import org.jclouds.rackspace.clouddns.v1.internal.BaseCloudDNSApiLiveTest; import org.jclouds.rackspace.clouddns.v1.internal.BaseCloudDNSApiLiveTest;
import org.jclouds.rest.RestContext;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -61,7 +59,7 @@ public class ReverseDNSApiLiveTest extends BaseCloudDNSApiLiveTest {
+ "-recordtest-jclouds.org"; + "-recordtest-jclouds.org";
private ComputeService computeService; private ComputeService computeService;
private RestContext<NovaApi, NovaAsyncApi> nova; private NovaApi nova;
private String serverId; private String serverId;
private URI serverURI; private URI serverURI;
private String serverIPv4; private String serverIPv4;
@ -82,14 +80,14 @@ public class ReverseDNSApiLiveTest extends BaseCloudDNSApiLiveTest {
.overrides(overrides) .overrides(overrides)
.buildView(ComputeServiceContext.class); .buildView(ComputeServiceContext.class);
computeService = context.getComputeService(); computeService = context.getComputeService();
nova = context.unwrap(); nova = context.unwrapApi(NovaApi.class);
Template template = computeService.templateBuilder().smallest().build(); Template template = computeService.templateBuilder().smallest().build();
NodeMetadata nodeMetadata = computeService.createNodesInGroup("jclouds-reverse-dns-test", 1, template).iterator().next(); NodeMetadata nodeMetadata = computeService.createNodesInGroup("jclouds-reverse-dns-test", 1, template).iterator().next();
serverId = nodeMetadata.getId(); serverId = nodeMetadata.getId();
serverURI = nodeMetadata.getUri(); serverURI = nodeMetadata.getUri();
ServerApi serverApi = nova.getApi().getServerApiForZone(nodeMetadata.getLocation().getParent().getId()); ServerApi serverApi = nova.getServerApiForZone(nodeMetadata.getLocation().getParent().getId());
Server server = serverApi.get(nodeMetadata.getProviderId()); Server server = serverApi.get(nodeMetadata.getProviderId());
serverIPv4 = server.getAccessIPv4(); serverIPv4 = server.getAccessIPv4();
serverIPv6 = server.getAccessIPv6(); serverIPv6 = server.getAccessIPv6();

View File

@ -27,13 +27,13 @@ import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.jclouds.hpcloud.compute.config.HPCloudComputeServiceContextModule; import org.jclouds.hpcloud.compute.config.HPCloudComputeServiceContextModule;
import org.jclouds.openstack.keystone.v2_0.config.AuthenticationApiModule;
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
import org.jclouds.openstack.nova.v2_0.NovaApiMetadata; import org.jclouds.openstack.nova.v2_0.NovaApiMetadata;
import org.jclouds.openstack.nova.v2_0.config.NovaHttpApiModule;
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule; import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
import org.jclouds.openstack.nova.v2_0.config.NovaRestClientModule;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata; import org.jclouds.providers.internal.BaseProviderMetadata;
@ -89,11 +89,11 @@ public class HPCloudComputeProviderMetadata extends BaseProviderMetadata {
.endpointName("identity service url ending in /v2.0/") .endpointName("identity service url ending in /v2.0/")
.defaultEndpoint("https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/") .defaultEndpoint("https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/")
.defaultModules(ImmutableSet.<Class<? extends Module>>builder() .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(MappedAuthenticationApiModule.class) .add(AuthenticationApiModule.class)
.add(KeystoneAuthenticationModule.class) .add(KeystoneAuthenticationModule.class)
.add(ZoneModule.class) .add(ZoneModule.class)
.add(NovaParserModule.class) .add(NovaParserModule.class)
.add(NovaRestClientModule.class) .add(NovaHttpApiModule.class)
.add(HPCloudComputeServiceContextModule.class).build()) .add(HPCloudComputeServiceContextModule.class).build())
.build()) .build())
.homepage(URI.create("http://hpcloud.com")) .homepage(URI.create("http://hpcloud.com"))

View File

@ -26,13 +26,13 @@ import java.util.Properties;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
import org.jclouds.openstack.nova.v2_0.NovaApiMetadata; import org.jclouds.openstack.nova.v2_0.NovaApiMetadata;
import org.jclouds.openstack.nova.v2_0.config.NovaHttpApiModule;
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule; import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
import org.jclouds.openstack.nova.v2_0.config.NovaRestClientModule;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata; import org.jclouds.providers.internal.BaseProviderMetadata;
import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationApiModule;
import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule; import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes; import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
import org.jclouds.rackspace.cloudidentity.v2_0.config.SyncToAsyncCloudIdentityAuthenticationApiModule;
import org.jclouds.rackspace.cloudservers.uk.config.CloudServersUKComputeServiceContextModule; import org.jclouds.rackspace.cloudservers.uk.config.CloudServersUKComputeServiceContextModule;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -81,11 +81,11 @@ public class CloudServersUKProviderMetadata extends BaseProviderMetadata {
.endpointName("identity service url ending in /v2.0/") .endpointName("identity service url ending in /v2.0/")
.documentation(URI.create("http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_preface.html#webhelp-currentid")) .documentation(URI.create("http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_preface.html#webhelp-currentid"))
.defaultModules(ImmutableSet.<Class<? extends Module>>builder() .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(SyncToAsyncCloudIdentityAuthenticationApiModule.class) .add(CloudIdentityAuthenticationApiModule.class)
.add(CloudIdentityAuthenticationModule.class) .add(CloudIdentityAuthenticationModule.class)
.add(ZoneModule.class) .add(ZoneModule.class)
.add(NovaParserModule.class) .add(NovaParserModule.class)
.add(NovaRestClientModule.class) .add(NovaHttpApiModule.class)
.add(CloudServersUKComputeServiceContextModule.class).build()) .add(CloudServersUKComputeServiceContextModule.class).build())
.build()) .build())
.homepage(URI.create("http://www.rackspace.co.uk/opencloud")) .homepage(URI.create("http://www.rackspace.co.uk/opencloud"))

View File

@ -26,13 +26,13 @@ import java.util.Properties;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
import org.jclouds.openstack.nova.v2_0.NovaApiMetadata; import org.jclouds.openstack.nova.v2_0.NovaApiMetadata;
import org.jclouds.openstack.nova.v2_0.config.NovaHttpApiModule;
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule; import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
import org.jclouds.openstack.nova.v2_0.config.NovaRestClientModule;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata; import org.jclouds.providers.internal.BaseProviderMetadata;
import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationApiModule;
import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule; import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes; import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
import org.jclouds.rackspace.cloudidentity.v2_0.config.SyncToAsyncCloudIdentityAuthenticationApiModule;
import org.jclouds.rackspace.cloudservers.us.config.CloudServersUSComputeServiceContextModule; import org.jclouds.rackspace.cloudservers.us.config.CloudServersUSComputeServiceContextModule;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -85,11 +85,11 @@ public class CloudServersUSProviderMetadata extends BaseProviderMetadata {
.endpointName("identity service url ending in /v2.0/") .endpointName("identity service url ending in /v2.0/")
.documentation(URI.create("http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/index.html")) .documentation(URI.create("http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/index.html"))
.defaultModules(ImmutableSet.<Class<? extends Module>>builder() .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(SyncToAsyncCloudIdentityAuthenticationApiModule.class) .add(CloudIdentityAuthenticationApiModule.class)
.add(CloudIdentityAuthenticationModule.class) .add(CloudIdentityAuthenticationModule.class)
.add(ZoneModule.class) .add(ZoneModule.class)
.add(NovaParserModule.class) .add(NovaParserModule.class)
.add(NovaRestClientModule.class) .add(NovaHttpApiModule.class)
.add(CloudServersUSComputeServiceContextModule.class).build()) .add(CloudServersUSComputeServiceContextModule.class).build())
.build()) .build())
.homepage(URI.create("http://www.rackspace.com/cloud/nextgen")) .homepage(URI.create("http://www.rackspace.com/cloud/nextgen"))