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

View File

@ -28,33 +28,23 @@ import java.net.URI;
import java.util.Properties;
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.KeystoneAuthenticationModule;
import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
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.config.NovaHttpApiModule;
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.rest.internal.BaseRestApiMetadata;
import org.jclouds.rest.internal.BaseHttpApiMetadata;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
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 {
/**
* @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;
};
public class NovaApiMetadata extends BaseHttpApiMetadata<NovaApi> {
@Override
public Builder toBuilder() {
@ -70,7 +60,7 @@ public class NovaApiMetadata extends BaseRestApiMetadata {
}
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
Properties properties = BaseHttpApiMetadata.defaultProperties();
// auth fail can happen while cloud-init applies keypair updates
properties.setProperty("jclouds.ssh.max-retries", "7");
properties.setProperty("jclouds.ssh.retry-auth", "true");
@ -86,30 +76,28 @@ public class NovaApiMetadata extends BaseRestApiMetadata {
return properties;
}
public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
public static class Builder extends BaseHttpApiMetadata.Builder<NovaApi, Builder> {
@SuppressWarnings("deprecation")
protected Builder() {
super(NovaApi.class, NovaAsyncApi.class);
id("openstack-nova")
.name("OpenStack Nova Diablo+ API")
.identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant")
.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/"))
.version("1.1")
.defaultEndpoint("http://localhost:5000/v2.0/")
.defaultProperties(NovaApiMetadata.defaultProperties())
.view(typeToken(ComputeServiceContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(MappedAuthenticationApiModule.class)
.add(AuthenticationApiModule.class)
.add(KeystoneAuthenticationModule.class)
.add(ZoneModule.class)
.add(NovaParserModule.class)
.add(NovaRestClientModule.class)
.add(NovaHttpApiModule.class)
.add(NovaComputeServiceContextModule.class).build());
}
@Override
public NovaApiMetadata build() {
return new NovaApiMetadata(this);

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

@ -86,7 +86,7 @@ public class NovaComputeServiceAdapter implements
this.zoneIds = checkNotNull(zoneIds, "zoneIds");
this.removeFloatingIpFromNodeAndDeallocate = checkNotNull(removeFloatingIpFromNodeAndDeallocate,
"removeFloatingIpFromNodeAndDeallocate");
this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");
this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");
}
/**
@ -117,7 +117,7 @@ public class NovaComputeServiceAdapter implements
Optional<String> privateKey = Optional.absent();
if (templateOptions.getKeyPairName() != null) {
options.keyPairName(templateOptions.getKeyPairName());
options.keyPairName(templateOptions.getKeyPairName());
KeyPair keyPair = keyPairCache.getIfPresent(ZoneAndName.fromZoneAndName(template.getLocation().getId(), templateOptions.getKeyPairName()));
if (keyPair != null && keyPair.getPrivateKey() != null) {
privateKey = Optional.of(keyPair.getPrivateKey());

View File

@ -15,10 +15,8 @@
* limitations under the License.
*/
package org.jclouds.openstack.nova.v2_0.config;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
import java.util.Map;
import java.util.Set;
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.ServerError;
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.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.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.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.config.HttpApiModule;
import org.jclouds.rest.functions.ImplicitOptionalConverter;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides;
/**
* Configures the Nova connection.
*
*/
@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()
.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();
public class NovaHttpApiModule extends HttpApiModule<NovaApi> {
@SuppressWarnings("unchecked")
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);
public NovaHttpApiModule() {
}
@Override

View File

@ -16,19 +16,39 @@
*/
package org.jclouds.openstack.nova.v2_0.extensions;
import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable;
import javax.inject.Named;
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.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;
/**
* Provides access to the OpenStack Compute (Nova) Availability Zone Extension API.
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AVAILABILITY_ZONE)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-availability-zone")
public interface AvailabilityZoneApi {
/**
* @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;
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.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 com.google.common.annotations.Beta;
/**
* Provides synchronous access to Consoles.
* Provides access to the OpenStack Compute (Nova) Consoles Extension API.
* <p/>
*
* @see ConsoleAsyncApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CONSOLES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface ConsolesApi {
/**
* Get the Console
* Gets the specified server Console.
*
* @param serverId Server id
* @param type see {@link Console.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,60 +17,114 @@
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.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.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;
/**
* 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.extensions.FlavorExtraSpecsAsyncApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLAVOR_EXTRA_SPECS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors")
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
*/
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
*
* @param flavorId the id of the flavor to modify
* @param specs the extra specs to apply
* @param flavorId the id of the flavor to modify
* @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
*
* @param flavorId the id of the flavor to modify
* @param key the extra spec key to retrieve
* @param id the id of the flavor to modify
* @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
*
* @param flavorId 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 value the value to associate with the key
* @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 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
*
* @param flavorId the id of the flavor to modify
* @param key the extra spec key to delete
* @param id the id of the flavor to modify
* @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;
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.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;
/**
* Provides synchronous access to Floating IPs.
* <p/>
*
* @see FloatingIPAsyncApi
* Provides access to the OpenStack Compute (Nova) Floating IP extension API.
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface FloatingIPApi {
/**
* List all Floating IP addresses
*
* Lists all Floating IP addresses
*
* @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
*/
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
*/
@Named("floatingIP:create")
@POST
@Path("/os-floating-ips")
@SelectJson("floating_ip")
@Produces(MediaType.APPLICATION_JSON)
@Payload("{}")
@Fallback(NullOnNotFoundOr404.class)
@Nullable
FloatingIP create();
/**
* Allocate a Floating IP address from a pool
* Allocates a Floating IP address from a pool
*
* @param pool
* Pool to allocate IP address from
* @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
* 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
*
* @param serverId
* the serverId
* Adds a Floating IP address to a Server
*
* @param id
* the server id
* @param address
* the IP address to add
*
*
* 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
*
* @param serverId
* the serverId
* Removes a Floating IP address from a Server
*
* @param id
* the server id
* @param address
* the IP address to remove
*
*
* 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;
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;
/**
* Provides asynchronous access to Host Administration features via the REST API.
* <p/>
*
* @see HostAdministrationAsyncApi
* Provides access to OpenStack Compute (Nova) Host Administration extension API.
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.HOSTS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-hosts")
public interface HostAdministrationApi {
/**
* Returns the list of hosts
*
* @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
*
* @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.
*
* @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.
*
* @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.
@ -69,34 +112,57 @@ public interface HostAdministrationApi {
*
* @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.
*
* @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.
*
* @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.
*
* @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.
*
* @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;
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.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;
/**
* Provide access to Host Aggregates in Nova (alias "OS-AGGREGATES")
*
* @see HostAggregateAsyncApi
* @see <a href="http://nova.openstack.org/api_ext/ext_aggregates.html"/>
* @see <a href="http://wiki.openstack.org/host-aggregates"/>
* Provide access to the OpenStack Compute (Nova) Host Aggregates extension API.
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AGGREGATES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-aggregates")
public interface HostAggregateApi {
/**
* Lists all 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.
*
* @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.
*
*
* @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.
*/
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.
*/
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
*/
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
*/
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
*/
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,63 +16,111 @@
*/
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;
/**
* Provides synchronous access to the OpenStack Nova Key Pair Extension API.
* <p/>
*
* @see KeyPairAsyncApi
* Provides access to the OpenStack Compute (Nova) Key Pair Extension API.
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-keypairs")
public interface KeyPairApi {
/**
* Lists all Key Pairs.
*
*
* @return all Key Pairs
*/
@Named("keypair:list")
@GET
@ResponseParser(ParseKeyPairs.class)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class)
FluentIterable<KeyPair> list();
/**
* Creates a {@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);
/**
* Creates a {@link KeyPair} with a public key.
*
*
* @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.
*
*
* @param name
* the name of the {@link KeyPair}
*
*
* @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}.
*
*
* @param name
* the name of the {@link KeyPair}
*
*
* @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;
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.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;
/**
* 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
* 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.
* <p/>
* 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
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.QUOTAS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-quota-sets")
public interface QuotaApi {
/**
* @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
*
* @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
*/
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;
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.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;
/**
* Provides synchronous access to Security Groups.
* <p/>
*
* @see SecurityGroupAsyncApi
* Provides access to the OpenStack Compute (Nova) Security Group extension API.
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SECURITY_GROUPS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface SecurityGroupApi {
/**
* List 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
*
*
* @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
*
*
* @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.
*
*
* @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.
*
*
* @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.
*
*
* @return a new Security Group Rule
*/
SecurityGroupRule createRuleAllowingSecurityGroupId(String parentGroup, Ingress ingress,
String groupId);
@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 createRuleAllowingSecurityGroupId(
@PayloadParam("parent_group_id") String parentGroup, Ingress ip_protocol,
@PayloadParam("group_id") String groupId);
/**
* Delete a Security Group Rule.
*
*
* @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;
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;
/**
* Provide access to the OpenStack Compute (Nova) Admin Server Actions Extension API.
*
* Provide additional actions for servers:
* 'suspend', 'resume', 'migrate', 'lock', 'unlock', 'resetNetwork', 'createBackup', 'pause', 'migrateLive',
* 'injectNetworkInfo', 'unpause'
*
* @see org.jclouds.openstack.nova.v2_0.extensions.ServerAdminAsyncApi
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.ADMIN_ACTIONS)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/{id}/action")
public interface ServerAdminApi {
/**
* Suspend a 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.
*
* @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.
*
* @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.
*
* @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.
*
* @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.
*
* @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.
@ -86,34 +137,63 @@ public interface ServerAdminApi {
* @param options optional rotation and/or metadata parameters
* @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.
*
* @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.
*
* @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.
*
* @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.
*
* @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;
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.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;
/**
* Provides synchronous access to Server details including security group, referred to as the CREATESERVEREXT extension
* in the nova documentation
* Provides access to the OpenStack Compute (Nova) Create Server extension API.
*
* This provides details including the security groups associated with a Server.
* <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 ServerWithSecurityGroupsAsyncApi
* @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)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-create-server-ext")
public interface ServerWithSecurityGroupsApi {
/**
* Retrieve details of the specified server, including security groups
*
* @param id id of the server
* @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;
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.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;
/**
* Provides asynchronous access to Simple Tenant Usage via the REST API.
* <p/>
*
* @see SimpleTenantUsageAsyncApi
* Provides access to the OpenStack Compute (Nova) Simple Tenant Usage extension API.
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SIMPLE_TENANT_USAGE)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-simple-tenant-usage")
public interface SimpleTenantUsageApi {
/**
* Retrieve tenant_usage for all tenants
* Retrieve tenant usage for all tenants.
*
* @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
*
* @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;
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;
/**
* Provides synchronous access to Virtual Interface features (VIFs).
*
* @see VirtualInterfaceAsyncApi
* Provides access to the OpenStack Compute (Nova) Virtual Interface (VIFs) extension API.
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VIRTUAL_INTERFACES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
public interface VirtualInterfaceApi {
/**
* 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;
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.VolumeAttachment;
import org.jclouds.openstack.nova.v2_0.domain.VolumeSnapshot;
@ -23,124 +38,210 @@ 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;
/**
* Provides synchronous access to Volumes.
* <p/>
*
* @see VolumeAsyncApi
* @see org.jclouds.openstack.nova.v2_0.extensions.VolumeAsyncApi
* Provides access to the OpenStack Compute (Nova) Volume extension API.
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface VolumeApi {
/**
* Returns a summary 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.
*
* @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 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
*
* @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.
*
* @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.
*
*
* @return all Floating IPs
* @deprecated To be removed in jclouds 1.7
* @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.
*
*
* @return data about the given volume attachment.
* @deprecated To be removed in jclouds 1.7
* @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
*
*
* @return data about the new volume attachment
* @deprecated To be removed in jclouds 1.7
* @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.
*
*
* @return true if successful
* @deprecated To be removed in jclouds 1.7
* @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.
*
* @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.
*
* @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 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
*/
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.
*
* @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,71 +16,117 @@
*/
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.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;
/**
* Provides synchronous access to Volume Attachments.
*
* This API strictly handles attaching Volumes to Servers. To create and manage Volumes you need to use one of the
* 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
* following APIs:
*
*
* 1. The Cinder API
* If your OpenStack deployment is Folsom or later and it supports the Cinder block storage service, use this API.
* @see org.jclouds.openstack.cinder.v1.features.VolumeApi
*
*
* 2. The nova-volume 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 VolumeAttachmentAsyncApi
*
*/
@Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
public interface VolumeAttachmentApi {
/**
* List Volume Attachments for a given Server.
*
*
* @param serverId The ID of 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.
*
*
* @param volumeId The ID of the Volume
* @param serverId The ID of the Server
* @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.
*
* Note: If you are using KVM as your hypervisor then the actual device name in the Server will be different than
*
* Note: If you are using KVM as your hypervisor then the actual device name in the Server will be different than
* the one specified. When the Server sees a new device, it picks the next available name (which in most cases is
* /dev/vdc) and the disk shows up there on the Server.
*
*
* @param serverId The ID of the Server
* @param volumeId The ID of the Volume
* @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.
*/
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.
*
*
* Note: Make sure you've unmounted the volume first. Failure to do so could result in failure or data loss.
*
*
* @param volumeId The ID of the Volume
* @param serverId The ID of the Server
* @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;
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.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;
/**
* Provides synchronous access to Volume Type features
* Provides access to the OpenStack Compute (Nova) Volume Type extension API.
*
* @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
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUME_TYPES)
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/os-volume-types")
public interface VolumeTypeApi {
/**
* @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
* @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
@ -55,23 +93,47 @@ public interface VolumeTypeApi {
* @param options optional settings for 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
*
* @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
* @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
*/
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
@ -79,7 +141,13 @@ public interface VolumeTypeApi {
* @param id the id of the volume type
* @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
@ -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 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
@ -96,5 +172,9 @@ public interface VolumeTypeApi {
* @param id the id of the volume type
* @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,62 +16,121 @@
*/
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.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.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.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/>
*
* @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 {
/**
* List 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)
*
*
* @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
*
*
* @param id
* id of the flavor
* @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
*
* @param flavor - flavor object
* @return newly created flavor
*/
Flavor create(Flavor flavor);
/**
* Create flavor according to the provided object
*
* @param flavor - flavor object
* @return newly created 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
*
* @param id - flavor id
*/
void delete(String id);
/**
* Delete flavor with a given id
*
* @param id - flavor 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,107 +17,186 @@
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.javax.annotation.Nullable;
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.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;
/**
* Provides synchronous access to Images.
* <p/>
*
* @see ImageAsyncApi
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/1.1/content/Servers-d1e2073.html"
* />
* Provides access to the OpenStack Compute (Nova) Image API.
*/
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
public interface ImageApi {
/**
* List 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)
*
*
* @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
*
*
* @param id
* id of the server
* @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
*
*
* @param id
* id of the image
* @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.
*
*
* @param id
* 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.
*
*
* @param id
* id of the image
* @param 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.
*
*
* @param id
* id of the image
* @param 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.
*
*
* @param id
* id of the image
* @param metadata
* a Map containing the metadata
* @return the value or null if not present
*/
@Named("image:getMetadata")
@GET
@Path("/{id}/metadata/{key}")
@ResponseParser(OnlyMetadataValueOrNull.class)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
String getMetadata(String id, String key);
String getMetadata(@PathParam("id") String id, @PathParam("key") String key);
/**
* Set a metadata item for an image.
*
*
* @param id
* id of the image
* @param key
@ -126,16 +205,27 @@ public interface ImageApi {
* the value of the metadata item
* @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.
*
*
* @param id
* id of the image
* @param key
* 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,59 +17,119 @@
package org.jclouds.openstack.nova.v2_0.features;
import com.google.common.base.Optional;
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.javax.annotation.Nullable;
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.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;
/**
* Provides synchronous access to Server.
* <p/>
*
* @see ServerAsyncApi
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/1.1/content/Servers-d1e2073.html"
* />
* Provides access to the OpenStack Compute (Nova) Server API.
*/
@RequestFilters(AuthenticateRequest.class)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
public interface ServerApi {
/**
* List 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)
*
*
* @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
*
*
* @param id
* id of the server
* @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
*
*
* @param name
* name of the server to create
* @param imageRef
@ -81,98 +141,151 @@ public interface ServerApi {
* request
* @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.
*
*
* @param id
* id of the server
* @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
*
*
* @param id
* 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
*
*
* @param id
* 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.
*
*
* @param id
* id of the server
* @param rebootType
* 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.
*
*
* @param id
* id of the server
* @param flavorId
* 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.
*
*
* @param id
* 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.
*
*
* @param id
* 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.
*
*
* @param id
* id of the server
* @param options
* 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.
*
*
* @param id
* id of the server
* @param adminPass
* 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.
*
*
* @param id
* id of the server
* @param newName
* 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.
@ -184,55 +297,88 @@ public interface ServerApi {
*
* @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.
*
*
* @param id
* id of the server
*
* @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.
*
*
* @param id
* id of the server
* @param 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.
*
*
* @param id
* id of the server
* @param 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.
*
*
* @param id
* id of the image
* @param metadata
* a Map containing the metadata
* @return the value or null if not present
*/
@Named("server:getMetadata")
@GET
@Path("/{id}/metadata/{key}")
@ResponseParser(OnlyMetadataValueOrNull.class)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
String getMetadata(String id, String key);
String getMetadata(@PathParam("id") String id, @PathParam("key") String key);
/**
* Set a metadata item for a server.
*
*
* @param id
* id of the image
* @param key
@ -241,34 +387,47 @@ public interface ServerApi {
* the value of the metadata item
* @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.
*
*
* @param id
* id of the image
* @param key
* 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.
* The information returned by this method is dependent on the hypervisor
* in use by the OpenStack installation and whether that hypervisor supports
* this method. More information can be found in the
* <a href="http://api.openstack.org/api-ref.html"> OpenStack API
* this method. More information can be found in the
* <a href="http://api.openstack.org/api-ref.html"> OpenStack API
* reference</a>. <br/>
* At the moment the returned response is a generic map. In future versions
* At the moment the returned response is a generic map. In future versions
* of OpenStack this might be subject to change.
*
*
* @param id
* id of the server
* @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

@ -89,14 +89,14 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
Template template = forNetworks.getInstance(TemplateBuilder.class).build();
template.getOptions().as(NovaTemplateOptions.class).networks("4ebd35cf-bfe7-4d93-b0d8-eb468ce2245a");
NovaComputeServiceAdapter adapter = forNetworks.getInstance(NovaComputeServiceAdapter.class);
NodeAndInitialCredentials<ServerInZone> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", template);
assertNotNull(server);
// Response irrelevant in this expect test - just verifying the request.
}
public void testCreateNodeWithGroupEncodedIntoNameWithDiskConfig() throws Exception {
HttpRequest createServer = HttpRequest
@ -124,7 +124,7 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
Template template = forDiskConfig.getInstance(TemplateBuilder.class).build();
template.getOptions().as(NovaTemplateOptions.class).diskConfig(Server.DISK_CONFIG_AUTO);
NovaComputeServiceAdapter adapter = forDiskConfig.getInstance(NovaComputeServiceAdapter.class);
NodeAndInitialCredentials<ServerInZone> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", template);
@ -240,7 +240,7 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
Template template = forSecurityGroups.getInstance(TemplateBuilder.class).build();
template.getOptions().as(NovaTemplateOptions.class).securityGroupNames("group1", "group2");
NovaComputeServiceAdapter adapter = forSecurityGroups.getInstance(NovaComputeServiceAdapter.class);
NodeAndInitialCredentials<ServerInZone> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92",
@ -255,7 +255,7 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
* authentication even be available.
*/
public void testWhenKeyPairPresentWeUsePrivateKeyAsCredentialNotPassword() throws Exception {
HttpRequest createServer = HttpRequest
.builder()
.method("POST")
@ -266,7 +266,7 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"key_name\":\"foo\"}}", "application/json"))
.build();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_server_no_adminpass.json", "application/json; charset=UTF-8")).build();
@ -282,16 +282,16 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
Template template = forSecurityGroups.getInstance(TemplateBuilder.class).build();
template.getOptions().as(NovaTemplateOptions.class).keyPairName("foo");
NovaComputeServiceAdapter adapter = forSecurityGroups.getInstance(NovaComputeServiceAdapter.class);
// we expect to have already an entry in the cache for the key
LoadingCache<ZoneAndName, KeyPair> keyPairCache = forSecurityGroups.getInstance(Key
.get(new TypeLiteral<LoadingCache<ZoneAndName, KeyPair>>() {
}));
keyPairCache.put(ZoneAndName.fromZoneAndName("az-1.region-a.geo-1", "foo"), KeyPair.builder().name("foo")
.privateKey("privateKey").build());
NodeAndInitialCredentials<ServerInZone> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92",
template);
assertNotNull(server);
@ -349,6 +349,7 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
.builder()
.method("POST")
.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)
.payload(payloadFromStringWithContentType(
"{\"suspend\":null}", "application/json"))
@ -412,7 +413,7 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC
public Injector apply(ComputeServiceContext input) {
return input.utils().injector();
}
@Override
protected Properties setupProperties() {
Properties overrides = super.setupProperties();

View File

@ -94,7 +94,7 @@ public class AllocateAndAddFloatingIpToNodeExpectTest extends BaseNovaComputeSer
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"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "*/*")
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).payload(
payloadFromStringWithContentType("{\"addFloatingIp\":{\"address\":\"" + address + "\"}}",
"application/json")).build();

View File

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

View File

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

View File

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

View File

@ -31,7 +31,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests annotation parsing of {@code KeyPairAsyncApi}
* Tests annotation parsing of {@code KeyPairApi}
*/
@Test(groups = "unit", testName = "KeyPairApiExpectTest")
public class KeyPairApiExpectTest extends BaseNovaApiExpectTest {
@ -128,7 +128,7 @@ public class KeyPairApiExpectTest extends BaseNovaApiExpectTest {
.builder()
.method("DELETE")
.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();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(202).build();

View File

@ -82,6 +82,7 @@ public class QuotaApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse,
HttpRequest.builder().endpoint(endpoint).method("PUT")
.addHeader("X-Auth-Token", authToken)
.addHeader("Accept", "application/json")
.payload(payloadFromResourceWithContentType("/quotas.json", MediaType.APPLICATION_JSON))
.build(),
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,
HttpRequest.builder().endpoint(endpoint).method("PUT")
.addHeader("X-Auth-Token", authToken)
.addHeader("Accept", "application/json")
.payload(payloadFromResourceWithContentType("/quotas.json", MediaType.APPLICATION_JSON))
.build(),
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;
/**
* Tests annotation parsing of {@code SecurityGroupAsyncApi}
* Tests annotation parsing of {@code SecurityGroupApi}
*/
@Test(groups = "unit", testName = "SecurityGroupApiExpectTest")
public class SecurityGroupApiExpectTest extends BaseNovaApiExpectTest {
@ -206,7 +206,7 @@ public class SecurityGroupApiExpectTest extends BaseNovaApiExpectTest {
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"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "*/*")
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).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;
/**
* Tests annotation parsing of {@code ExtensionAsyncApi}
* Tests annotation parsing of {@code ExtensionApi}
*/
@Test(groups = "unit", testName = "ExtensionApiExpectTest")
public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
public void testListExtensionsWhenResponseIs2xx() throws Exception {
HttpRequest listExtensions = HttpRequest
.builder()
HttpRequest listExtensions = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listExtensionsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/extension_list.json")).build();
@ -57,12 +57,12 @@ public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
}
public void testListExtensionsWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listExtensions = HttpRequest
.builder()
HttpRequest listExtensions = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listExtensionsResponse = HttpResponse.builder().statusCode(404).build();
@ -74,13 +74,12 @@ public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
// TODO: gson deserializer for Multimap
public void testGetExtensionByAliasWhenResponseIs2xx() throws Exception {
HttpRequest getExtension = HttpRequest
.builder()
HttpRequest getExtension = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions/RS-PIE")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getExtensionResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/extension_details.json")).build();
@ -93,12 +92,12 @@ public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
}
public void testGetExtensionByAliasWhenResponseIs404() throws Exception {
HttpRequest getExtension = HttpRequest
.builder()
HttpRequest getExtension = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/extensions/RS-PIE")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getExtensionResponse = HttpResponse.builder().statusCode(404)
.payload(payloadFromResource("/extension_details.json")).build();
@ -107,7 +106,5 @@ public class ExtensionApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, getExtension, getExtensionResponse);
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;
/**
* Tests annotation parsing of {@code FlavorAsyncApi}
* Tests annotation parsing of {@code FlavorApi}
*/
@Test(groups = "unit", testName = "FlavorApiExpectTest")
public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
public void testListFlavorsWhenResponseIs2xx() throws Exception {
HttpRequest listFlavors = HttpRequest
.builder()
HttpRequest listFlavors = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listFlavorsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/flavor_list.json")).build();
@ -63,12 +63,12 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
}
public void testListFlavorsWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listFlavors = HttpRequest
.builder()
HttpRequest listFlavors = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listFlavorsResponse = HttpResponse.builder().statusCode(404).build();
@ -80,13 +80,12 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
// TODO: gson deserializer for Multimap
public void testGetFlavorWhenResponseIs2xx() throws Exception {
HttpRequest getFlavor = HttpRequest
.builder()
HttpRequest getFlavor = HttpRequest.builder()
.method("GET")
.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("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getFlavorResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/flavor_details.json")).build();
@ -100,8 +99,7 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
}
public void testGetFlavorWhenResponseIs404() throws Exception {
HttpRequest getFlavor = HttpRequest
.builder()
HttpRequest getFlavor = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors/123")
.addHeader("Accept", "application/json")
@ -114,19 +112,17 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, getFlavor, getFlavorResponse);
assertNull(apiWhenNoFlavorsExist.getFlavorApiForZone("az-1.region-a.geo-1").get("123"));
}
public void testCreateFlavor200() throws Exception {
ParseCreateFlavorTest parser = new ParseCreateFlavorTest();
HttpRequest listFlavors = HttpRequest
.builder()
ParseCreateFlavorTest parser = new ParseCreateFlavorTest();
HttpRequest listFlavors = HttpRequest.builder()
.method(HttpMethod.POST)
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors")
.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)
.addHeader("X-Auth-Token", authToken)
.payload(payloadFromResource(parser.resource())).build();
HttpResponse listFlavorsResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource(parser.resource())).build();
@ -135,25 +131,23 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
assertEquals(
api.getFlavorApiForZone("az-1.region-a.geo-1").create(Flavor.builder()
.id("1cb47a44-9b84-4da4-bf81-c1976e8414ab")
.name("128 MB Server").ram(128).vcpus(1)
.disk(10).build())
.id("1cb47a44-9b84-4da4-bf81-c1976e8414ab")
.name("128 MB Server").ram(128).vcpus(1)
.disk(10).build())
.toString(), parser.expected().toString());
}
public void testDeleteFlavor202() throws Exception {
String flavorId = "1cb47a44-9b84-4da4-bf81-c1976e8414ab";
HttpRequest updateMetadata = HttpRequest
.builder()
HttpRequest updateMetadata = HttpRequest.builder()
.method(HttpMethod.DELETE)
.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)
.build();
HttpResponse updateMetadataResponse = HttpResponse.builder().statusCode(204).build();
NovaApi api = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, updateMetadata, updateMetadataResponse);

View File

@ -35,17 +35,18 @@ import com.google.common.collect.ImmutableMap;
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 void testListImagesWhenResponseIs2xx() throws Exception {
HttpRequest list = HttpRequest
.builder()
HttpRequest list = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_list.json")).build();
@ -60,12 +61,12 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
}
public void testListImagesWhenReponseIs404IsEmpty() throws Exception {
HttpRequest list = HttpRequest
.builder()
HttpRequest list = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
@ -77,12 +78,12 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
public void testGetImageWhenResponseIs2xx() throws Exception {
HttpRequest getImage = HttpRequest
.builder()
HttpRequest getImage = HttpRequest.builder()
.method("GET")
.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("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getImageResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_details.json")).build();
@ -96,46 +97,43 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
}
public void testGetImageWhenResponseIs404() throws Exception {
HttpRequest getImage = HttpRequest
.builder()
HttpRequest getImage = HttpRequest.builder()
.method("GET")
.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("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getImageResponse = HttpResponse.builder().statusCode(404).build();
NovaApi apiWhenNoImagesExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, getImage, getImageResponse);
assertNull(apiWhenNoImagesExist.getImageApiForZone("az-1.region-a.geo-1").get(
"52415800-8b69-11e0-9b19-734f5736d2a2"));
assertNull(apiWhenNoImagesExist.getImageApiForZone("az-1.region-a.geo-1").get("52415800-8b69-11e0-9b19-734f5736d2a2"));
}
public void testListMetadataWhenResponseIs2xx() throws Exception {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
HttpRequest getMetadata = HttpRequest
.builder()
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
HttpRequest getMetadata = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_list.json")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, getMetadata, getMetadataResponse);
assertEquals(apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").getMetadata(imageId).toString(),
assertEquals(apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").getMetadata(imageId).toString(),
new ParseMetadataListTest().expected().toString());
}
public void testListMetadataWhenResponseIs404() throws Exception {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
HttpRequest getMetadata = HttpRequest
.builder()
HttpRequest getMetadata = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "*/*")
@ -162,22 +160,22 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
.put("Image Version", "2.1")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "application/json")
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_list.json")).build();
NovaApi apiWhenImageExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
assertEquals(apiWhenImageExists.getImageApiForZone("az-1.region-a.geo-1").setMetadata(imageId, metadata).toString(),
assertEquals(apiWhenImageExists.getImageApiForZone("az-1.region-a.geo-1").setMetadata(imageId, metadata).toString(),
new ParseMetadataListTest().expected().toString());
}
@ -187,14 +185,14 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Label", "Web Head 1")
.put("Image Version", "2.1")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "*/*")
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404).build();
@ -217,22 +215,22 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata")
.addHeader("Accept", "application/json")
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_updated.json")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
assertEquals(apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").updateMetadata(imageId, metadata).toString(),
assertEquals(apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").updateMetadata(imageId, metadata).toString(),
new ParseMetadataUpdateTest().expected().toString());
}
@ -243,8 +241,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + imageId + "/metadata")
.addHeader("Accept", "application/json")
@ -259,7 +256,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
try {
apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").setMetadata(imageId, metadata);
apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").setMetadata(imageId, metadata);
fail("Expected an exception.");
} catch (Exception e) {
// expected
@ -270,8 +267,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image%20Version";
HttpRequest getMetadata = HttpRequest
.builder()
HttpRequest getMetadata = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key)
.addHeader("Accept", "application/json")
@ -280,11 +276,11 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
HttpResponse getMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromString("{\"metadata\":{\"Image Version\":\"2.5\"}}")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, getMetadata, getMetadataResponse);
assertEquals(apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").getMetadata(imageId, "Image Version").toString(),
assertEquals(apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").getMetadata(imageId, "Image Version").toString(),
"2.5");
}
@ -292,8 +288,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image%20Version";
HttpRequest getMetadata = HttpRequest
.builder()
HttpRequest getMetadata = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + key)
.addHeader("Accept", "application/json")
@ -313,8 +308,7 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image Version";
HttpRequest updateMetadata = HttpRequest
.builder()
HttpRequest updateMetadata = HttpRequest.builder()
.method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId + "/metadata/" + "Image%20Version")
.addHeader("Accept", "application/json")
@ -324,28 +318,27 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
HttpResponse updateMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\"metadata\":{\"Image Version\":\"2.5\"}}", "application/json")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, updateMetadata, updateMetadataResponse);
assertEquals(apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").updateMetadata(imageId, key, "2.5").toString(),
assertEquals(apiWhenServerExists.getImageApiForZone("az-1.region-a.geo-1").updateMetadata(imageId, key, "2.5").toString(),
"2.5");
}
public void testDeleteMetadataItemWhenResponseIs2xx() throws Exception {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image%20Version";
HttpRequest deleteMetadata = HttpRequest
.builder()
HttpRequest deleteMetadata = HttpRequest.builder()
.method("DELETE")
.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)
.build();
HttpResponse deleteMetadataResponse = HttpResponse.builder().statusCode(204).build();
NovaApi apiWhenImageExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, deleteMetadata, deleteMetadataResponse);
@ -356,11 +349,10 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "52415800-8b69-11e0-9b19-734f5736d2a2";
String key = "Image%20Version";
HttpRequest deleteMetadata = HttpRequest
.builder()
HttpRequest deleteMetadata = HttpRequest.builder()
.method("DELETE")
.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)
.build();
@ -370,6 +362,5 @@ public class ImageApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, deleteMetadata, deleteMetadataResponse);
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.ParseMetadataUpdateTest;
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.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
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 void testListServersWhenResponseIs2xx() throws Exception {
HttpRequest listServers = HttpRequest
.builder()
HttpRequest listServers = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json")
@ -66,8 +65,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
}
public void testListServersWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listServers = HttpRequest
.builder()
HttpRequest listServers = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json")
@ -118,17 +116,15 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
}
public void testCreateServerWhenResponseIs202() throws Exception {
HttpRequest createServer = HttpRequest
.builder()
HttpRequest createServer = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType(
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\"}}", "application/json"))
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\"}}", "application/json"))
.build();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.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 {
HttpRequest createServer = HttpRequest
.builder()
HttpRequest createServer = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.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"))
.build();
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();
@ -164,22 +158,18 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
}
public void testCreateServerWithSecurityGroupsWhenResponseIs202() throws Exception {
HttpRequest createServer = HttpRequest
.builder()
HttpRequest createServer = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType(
"{\"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();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_server.json", "application/json; charset=UTF-8")).build();
NovaApi apiWithNewServer = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, createServer, createServerResponse);
@ -189,22 +179,18 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
}
public void testCreateServerWithNetworksWhenResponseIs202() throws Exception {
HttpRequest createServer = HttpRequest
.builder()
HttpRequest createServer = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType(
"{\"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();
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/new_server.json", "application/json; charset=UTF-8")).build();
NovaApi apiWithNewServer = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, createServer, createServerResponse);
@ -214,24 +200,20 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
}
public void testCreateServerWithDiskConfigAuto() throws Exception {
HttpRequest createServer = HttpRequest
.builder()
HttpRequest createServer = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType(
"{\"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();
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();
NovaApi apiWithNewServer = requestsSendResponses(
keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess,
keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess,
createServer, createServerResponse);
assertEquals(apiWithNewServer.getServerApiForZone("az-1.region-a.geo-1").create("test-e92", "1241",
@ -240,24 +222,20 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
}
public void testCreateServerWithDiskConfigManual() throws Exception {
HttpRequest createServer = HttpRequest
.builder()
HttpRequest createServer = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType(
"{\"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();
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();
NovaApi apiWithNewServer = requestsSendResponses(
keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess,
keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess,
createServer, createServerResponse);
assertEquals(apiWithNewServer.getServerApiForZone("az-1.region-a.geo-1").create("test-e92", "1241",
@ -267,11 +245,10 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
public void testRebuildServerWhenResponseIs202() throws Exception {
String serverId = "52415800-8b69-11e0-9b19-734f565bc83b";
HttpRequest rebuildServer = HttpRequest
.builder()
HttpRequest rebuildServer = HttpRequest.builder()
.method("POST")
.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)
.payload(payloadFromStringWithContentType(
"{\"rebuild\":{\"adminPass\":\"password\",\"imageRef\":\"1234\",\"name\":\"newName\",\"accessIPv4\":\"1.1.1.1\",\"accessIPv6\":\"fe80::100\"}}", "application/json"))
@ -292,20 +269,18 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
String imageId = "456";
String imageName = "foo";
HttpRequest createImage = HttpRequest
.builder()
HttpRequest createImage = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType(
"{\"createImage\":{\"name\":\"" + imageName + "\", \"metadata\": {}}}", "application/json"))
.build();
.build();
HttpResponse createImageResponse = HttpResponse.builder()
.statusCode(200)
.headers(
ImmutableMultimap.<String, String> builder()
.headers(ImmutableMultimap.<String, String> builder()
.put("Location", "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/images/" + imageId).build()).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
@ -319,17 +294,17 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
String serverId = "123";
String imageName = "foo";
HttpRequest createImage = HttpRequest
.builder()
HttpRequest createImage = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType(
"{\"createImage\":{\"name\":\"" + imageName + "\", \"metadata\": {}}}", "application/json"))
.build();
.build();
HttpResponse createImageResponse = HttpResponse.builder().statusCode(404).build();
NovaApi apiWhenServerDoesNotExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, createImage, createImageResponse);
@ -340,18 +315,17 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
// expected
}
}
public void testStopServerWhenResponseIs2xx() throws Exception {
String serverId = "123";
HttpRequest stopServer = HttpRequest
.builder()
HttpRequest stopServer = HttpRequest.builder()
.method("POST")
.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)
.payload(payloadFromStringWithContentType(
"{\"os-stop\":null}", "application/json"))
.build();
.build();
HttpResponse stopServerResponse = HttpResponse.builder().statusCode(202).build();
@ -360,19 +334,17 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").stop(serverId);
}
public void testStopServerWhenResponseIs404() throws Exception {
String serverId = "123";
HttpRequest stopServer = HttpRequest
.builder()
HttpRequest stopServer = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/action")
.addHeader("Accept", "*/*")
.addHeader("X-Auth-Token", authToken)
.payload(payloadFromStringWithContentType(
"{\"os-stop\":null}", "application/json"))
.build();
.build();
HttpResponse stopServerResponse = HttpResponse.builder().statusCode(404).build();
@ -386,19 +358,18 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
// expected
}
}
public void testStartServerWhenResponseIs2xx() throws Exception {
String serverId = "123";
HttpRequest startServer = HttpRequest
.builder()
.method("POST")
.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)
.payload(payloadFromStringWithContentType(
"{\"os-start\":null}", "application/json"))
.build();
.build();
HttpResponse startServerResponse = HttpResponse.builder().statusCode(202).build();
@ -407,18 +378,17 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").start(serverId);
}
public void testStartServerWhenResponseIs404() throws Exception {
String serverId = "123";
HttpRequest startServer = HttpRequest
.builder()
HttpRequest startServer = HttpRequest.builder()
.method("POST")
.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)
.payload(payloadFromStringWithContentType(
"{\"os-startp\":null}", "application/json"))
.build();
"{\"os-start\":null}", "application/json"))
.build();
HttpResponse startServerResponse = HttpResponse.builder().statusCode(404).build();
@ -435,29 +405,26 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
public void testListMetadataWhenResponseIs2xx() throws Exception {
String serverId = "123";
HttpRequest getMetadata = HttpRequest
.builder()
HttpRequest getMetadata = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse getMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_list.json")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, getMetadata, getMetadataResponse);
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").getMetadata(serverId).toString(),
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").getMetadata(serverId).toString(),
new ParseMetadataListTest().expected().toString());
}
public void testListMetadataWhenResponseIs404() throws Exception {
String serverId = "123";
HttpRequest getMetadata = HttpRequest
.builder()
HttpRequest getMetadata = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "*/*")
@ -470,7 +437,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, getMetadata, getMetadataResponse);
try {
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").getMetadata(serverId);
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").getMetadata(serverId);
fail("Expected an exception.");
} catch (Exception e) {
// expected
@ -484,22 +451,22 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Image Version", "2.1")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json")
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_list.json")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata).toString(),
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata).toString(),
new ParseMetadataListTest().expected().toString());
}
@ -509,14 +476,14 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Label", "Web Head 1")
.put("Image Version", "2.1")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("PUT")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "*/*")
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404).build();
@ -525,7 +492,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
try {
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata);
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata);
fail("Expected an exception.");
} catch (Exception e) {
// expected
@ -539,22 +506,22 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json")
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_updated.json")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").updateMetadata(serverId, metadata).toString(),
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").updateMetadata(serverId, metadata).toString(),
new ParseMetadataUpdateTest().expected().toString());
}
@ -565,13 +532,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("POST")
.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)
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404)
@ -581,7 +548,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
try {
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata);
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata);
fail("Expected an exception.");
} catch (Exception e) {
// expected
@ -602,11 +569,11 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
HttpResponse getMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_item.json")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, getMetadata, getMetadataResponse);
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").getMetadata(serverId, key).toString(),
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").getMetadata(serverId, key).toString(),
"Web Head 1");
}
@ -616,13 +583,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Label", "Web Head 1")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json")
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404)
@ -632,7 +599,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
try {
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata);
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata);
fail("Expected an exception.");
} catch (Exception e) {
// expected
@ -646,22 +613,22 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json")
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/metadata_updated.json")).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").updateMetadata(serverId, metadata).toString(),
assertEquals(apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").updateMetadata(serverId, metadata).toString(),
new ParseMetadataUpdateTest().expected().toString());
}
@ -672,13 +639,13 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
.put("Server Description", "Simple Server")
.build();
HttpRequest setMetadata = HttpRequest
.builder()
HttpRequest setMetadata = HttpRequest.builder()
.method("POST")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/metadata")
.addHeader("Accept", "application/json")
.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();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404)
@ -688,7 +655,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, setMetadata, setMetadataResponse);
try {
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata);
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").setMetadata(serverId, metadata);
fail("Expected an exception.");
} catch (Exception e) {
// expected
@ -699,32 +666,29 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
String serverId = "123";
String key = "Server%20Label";
HttpRequest updateMetadata = HttpRequest
.builder()
HttpRequest updateMetadata = HttpRequest.builder()
.method("DELETE")
.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)
.build();
HttpResponse updateMetadataResponse = HttpResponse.builder().statusCode(204).build();
NovaApi apiWhenServerExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, updateMetadata, updateMetadataResponse);
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").deleteMetadata(serverId, key);
}
public void testDeleteMetadataItemWhenResponseIs404() throws Exception {
String serverId = "123";
String key = "Server%20Label";
HttpRequest deleteMetadata = HttpRequest
.builder()
HttpRequest deleteMetadata = HttpRequest.builder()
.method("DELETE")
.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)
.build();
@ -734,21 +698,17 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
responseWithKeystoneAccess, deleteMetadata, deleteMetadataResponse);
apiWhenServerExists.getServerApiForZone("az-1.region-a.geo-1").deleteMetadata(serverId, key);
}
public void testGetDiagnosticsWhenResponseIs200() throws Exception {
String serverId = "123";
HttpRequest getDiagnostics = HttpRequest
.builder()
HttpRequest getDiagnostics = HttpRequest.builder()
.method("GET")
.addHeader("Accept", "application/json")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers/" + serverId + "/diagnostics")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse serverDiagnosticsResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
.payload(payloadFromResourceWithContentType("/server_diagnostics.json", "application/json; charset=UTF-8")).build();
@ -757,13 +717,10 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
assertEquals(apiWithNewServer.getServerApiForZone("az-1.region-a.geo-1").getDiagnostics(serverId),
new ParseServerDiagnostics().expected());
}
public void testGetDiagnosticsWhenResponseIs403Or404Or500() throws Exception {
String serverId = "123";
HttpRequest getDiagnostics = HttpRequest
.builder()
HttpRequest getDiagnostics = HttpRequest.builder()
.method("GET")
.addHeader("Accept", "application/json")
.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());
}
}
}

View File

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

View File

@ -27,13 +27,13 @@ import java.net.URI;
import java.util.Properties;
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.KeystoneAuthenticationModule;
import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
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.config.NovaHttpApiModule;
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.internal.BaseProviderMetadata;
@ -89,11 +89,11 @@ public class HPCloudComputeProviderMetadata extends BaseProviderMetadata {
.endpointName("identity service url ending in /v2.0/")
.defaultEndpoint("https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/")
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(MappedAuthenticationApiModule.class)
.add(AuthenticationApiModule.class)
.add(KeystoneAuthenticationModule.class)
.add(ZoneModule.class)
.add(NovaParserModule.class)
.add(NovaRestClientModule.class)
.add(NovaHttpApiModule.class)
.add(HPCloudComputeServiceContextModule.class).build())
.build())
.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.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.NovaRestClientModule;
import org.jclouds.providers.ProviderMetadata;
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.CloudIdentityCredentialTypes;
import org.jclouds.rackspace.cloudidentity.v2_0.config.SyncToAsyncCloudIdentityAuthenticationApiModule;
import org.jclouds.rackspace.cloudservers.uk.config.CloudServersUKComputeServiceContextModule;
import com.google.common.collect.ImmutableSet;
@ -81,11 +81,11 @@ public class CloudServersUKProviderMetadata extends BaseProviderMetadata {
.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"))
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(SyncToAsyncCloudIdentityAuthenticationApiModule.class)
.add(CloudIdentityAuthenticationApiModule.class)
.add(CloudIdentityAuthenticationModule.class)
.add(ZoneModule.class)
.add(NovaParserModule.class)
.add(NovaRestClientModule.class)
.add(NovaHttpApiModule.class)
.add(CloudServersUKComputeServiceContextModule.class).build())
.build())
.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.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.NovaRestClientModule;
import org.jclouds.providers.ProviderMetadata;
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.CloudIdentityCredentialTypes;
import org.jclouds.rackspace.cloudidentity.v2_0.config.SyncToAsyncCloudIdentityAuthenticationApiModule;
import org.jclouds.rackspace.cloudservers.us.config.CloudServersUSComputeServiceContextModule;
import com.google.common.collect.ImmutableSet;
@ -85,11 +85,11 @@ public class CloudServersUSProviderMetadata extends BaseProviderMetadata {
.endpointName("identity service url ending in /v2.0/")
.documentation(URI.create("http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/index.html"))
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(SyncToAsyncCloudIdentityAuthenticationApiModule.class)
.add(CloudIdentityAuthenticationApiModule.class)
.add(CloudIdentityAuthenticationModule.class)
.add(ZoneModule.class)
.add(NovaParserModule.class)
.add(NovaRestClientModule.class)
.add(NovaHttpApiModule.class)
.add(CloudServersUSComputeServiceContextModule.class).build())
.build())
.homepage(URI.create("http://www.rackspace.com/cloud/nextgen"))