mirror of https://github.com/apache/jclouds.git
Fixes OpenStack extension namespace configuration
* Improves extension namespace configuration to use Guice multibindings so each provider can cleanly provide their own namespaces. * Fixes the HPCloud Compute volume attachment namespace and adds the corresponding live tests. * Fixes the Rackspace CloudServers UK volume attachment namespace.
This commit is contained in:
parent
8217248571
commit
4db2b75add
|
@ -75,9 +75,8 @@
|
|||
</dependency>
|
||||
<!-- for ohai -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
<version>3.0</version>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
</dependency>
|
||||
<!-- for transient chef provider -->
|
||||
<dependency>
|
||||
|
|
|
@ -51,6 +51,11 @@
|
|||
<artifactId>jclouds-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- for the extension namespaces -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.keystone.v2_0.config;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
|
||||
@Qualifier
|
||||
public @interface Aliases {
|
||||
|
||||
}
|
|
@ -49,11 +49,11 @@ import com.google.common.base.Suppliers;
|
|||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
|
||||
/**
|
||||
* Configures the Keystone API.
|
||||
|
@ -91,17 +91,16 @@ public class KeystoneHttpApiModule extends HttpApiModule<KeystoneApi> {
|
|||
}
|
||||
}
|
||||
|
||||
// Allow providers to cleanly contribute their own aliases
|
||||
public static MapBinder<URI, URI> aliasBinder(Binder binder) {
|
||||
return MapBinder.newMapBinder(binder, URI.class, URI.class, Aliases.class).permitDuplicates();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public Multimap<URI, URI> aliases() {
|
||||
return ImmutableMultimap.<URI, URI>builder()
|
||||
.build();
|
||||
aliasBinder(binder());
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
@ -23,18 +23,20 @@ import static org.jclouds.util.Optionals2.unwrapIfOptional;
|
|||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.config.Aliases;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.reflect.InvocationSuccess;
|
||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* We use the annotation {@link org.jclouds.openstack.services.Extension} to bind a class that implements an extension
|
||||
|
@ -43,13 +45,13 @@ import com.google.common.collect.Multimap;
|
|||
public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet implements
|
||||
ImplicitOptionalConverter {
|
||||
private final LoadingCache<String, Set<? extends Extension>> extensions;
|
||||
private final Multimap<URI, URI> aliases;
|
||||
private final Map<URI, Set<URI>> aliases;
|
||||
|
||||
@Inject
|
||||
public PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet(
|
||||
LoadingCache<String, Set<? extends Extension>> extensions, Multimap<URI, URI> aliases) {
|
||||
this.extensions = checkNotNull(extensions, "extensions");
|
||||
this.aliases = aliases == null ? ImmutableMultimap.<URI, URI> of() : ImmutableMultimap.copyOf(aliases);
|
||||
PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet(
|
||||
LoadingCache<String, Set<? extends Extension>> extensions, @Aliases Map<URI, Set<URI>> aliases) {
|
||||
this.extensions = extensions;
|
||||
this.aliases = aliases == null ? ImmutableMap.<URI, Set<URI>> of() : ImmutableMap.copyOf(aliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,12 +62,13 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
|||
if (ext.isPresent()) {
|
||||
URI namespace = URI.create(ext.get().namespace());
|
||||
List<Object> args = input.getInvocation().getArgs();
|
||||
Set<URI> aliasesForNamespace = aliases.containsKey(namespace) ? aliases.get(namespace) : Sets.<URI> newHashSet();
|
||||
if (args.isEmpty()) {
|
||||
if (any(extensions.getUnchecked(""), namespaceOrAliasEquals(namespace, aliases.get(namespace))))
|
||||
if (any(extensions.getUnchecked(""), namespaceOrAliasEquals(namespace, aliasesForNamespace)))
|
||||
return input.getResult();
|
||||
} else if (args.size() == 1) {
|
||||
String arg0 = checkNotNull(args.get(0), "arg[0] in %s", input).toString();
|
||||
if (any(extensions.getUnchecked(arg0), namespaceOrAliasEquals(namespace, aliases.get(namespace))))
|
||||
if (any(extensions.getUnchecked(arg0), namespaceOrAliasEquals(namespace, aliasesForNamespace)))
|
||||
return input.getResult();
|
||||
} else {
|
||||
throw new RuntimeException(String.format("expecting zero or one args %s", input));
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.Aliases;
|
||||
import org.jclouds.openstack.v2_0.ServiceType;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.reflect.Invocation;
|
||||
|
@ -44,6 +45,7 @@ import com.google.common.collect.Multimap;
|
|||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
|
||||
@Test(groups = "unit", testName = "PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSetTest")
|
||||
public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSetTest {
|
||||
|
@ -138,6 +140,13 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
|||
new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
MapBinder<URI, URI> aliasBindings = MapBinder.newMapBinder(binder(),
|
||||
URI.class, URI.class, Aliases.class).permitDuplicates();
|
||||
for (URI key : aliases.keySet()) {
|
||||
for (URI value : aliases.get(key)) {
|
||||
aliasBindings.addBinding(key).toInstance(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -145,10 +154,6 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
|||
return extensionsForRegion;
|
||||
}
|
||||
|
||||
@Provides
|
||||
Multimap<URI, URI> getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
}).getInstance(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
|
||||
return fn;
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
<artifactId>openstack-keystone</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- for the extension namespaces -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds</groupId>
|
||||
<artifactId>jclouds-compute</artifactId>
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.config;
|
||||
|
||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneHttpApiModule.aliasBinder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -39,9 +41,8 @@ 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.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
|
||||
/**
|
||||
* Configures the Nova connection.
|
||||
|
@ -57,45 +58,44 @@ public class NovaHttpApiModule extends HttpApiModule<NovaApi> {
|
|||
protected void configure() {
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
super.configure();
|
||||
bindDefaultAliases();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public Multimap<URI, URI> aliases() {
|
||||
return ImmutableMultimap.<URI, URI>builder()
|
||||
.put(URI.create(ExtensionNamespaces.SECURITY_GROUPS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/securitygroups/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.FLOATING_IPS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/floating_ips/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.KEYPAIRS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/keypairs/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.SIMPLE_TENANT_USAGE),
|
||||
URI.create("http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.HOSTS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUMES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VIRTUAL_INTERFACES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.CREATESERVEREXT),
|
||||
URI.create("http://docs.openstack.org/compute/ext/createserverext/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.ADMIN_ACTIONS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/admin-actions/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.AGGREGATES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/aggregates/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.FLAVOR_EXTRA_SPECS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/flavor_extra_specs/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.QUOTAS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUME_TYPES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/volume_types/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.AVAILABILITY_ZONE),
|
||||
URI.create("http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUME_ATTACHMENTS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/os-volume-attachment-update/api/v2"))
|
||||
.put(URI.create(ExtensionNamespaces.ATTACH_INTERFACES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/interfaces/api/v1.1"))
|
||||
.build();
|
||||
// Intentionally private so subclasses use the Guice multibindings to contribute their aliases
|
||||
private void bindDefaultAliases() {
|
||||
MapBinder<URI, URI> aliases = aliasBinder(binder());
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.SECURITY_GROUPS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/securitygroups/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.FLOATING_IPS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/floating_ips/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.KEYPAIRS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/keypairs/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.SIMPLE_TENANT_USAGE)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.HOSTS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.VOLUMES)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.VIRTUAL_INTERFACES)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.CREATESERVEREXT)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/createserverext/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.ADMIN_ACTIONS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/admin-actions/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.AGGREGATES)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/aggregates/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.FLAVOR_EXTRA_SPECS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/flavor_extra_specs/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.QUOTAS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.VOLUME_TYPES)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/volume_types/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.AVAILABILITY_ZONE)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.VOLUME_ATTACHMENTS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/os-volume-attachment-update/api/v2"));
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.ATTACH_INTERFACES)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/interfaces/api/v1.1"));
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -104,7 +104,7 @@ public class NovaHttpApiModule extends HttpApiModule<NovaApi> {
|
|||
return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS)
|
||||
.build(new CacheLoader<String, Set<? extends Extension>>() {
|
||||
@Override
|
||||
public Set<? extends Extension> load(String key) throws Exception {
|
||||
public Set<? extends Extension> load(final String key) throws Exception {
|
||||
return novaApi.get().getExtensionApi(key).list();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.concurrent.TimeoutException;
|
|||
|
||||
import org.jclouds.ContextBuilder;
|
||||
import org.jclouds.openstack.cinder.v1.CinderApi;
|
||||
import org.jclouds.openstack.cinder.v1.CinderApiMetadata;
|
||||
import org.jclouds.openstack.cinder.v1.domain.Volume;
|
||||
import org.jclouds.openstack.cinder.v1.features.VolumeApi;
|
||||
import org.jclouds.openstack.cinder.v1.options.CreateVolumeOptions;
|
||||
|
@ -49,6 +50,7 @@ public class VolumeAttachmentApiLiveTest extends BaseNovaApiLiveTest {
|
|||
private Server server;
|
||||
|
||||
protected String volumeProvider;
|
||||
protected String volumeProviderVersion;
|
||||
protected int volumeSizeGB;
|
||||
protected String deviceId = "/dev/wtf";
|
||||
|
||||
|
@ -56,6 +58,8 @@ public class VolumeAttachmentApiLiveTest extends BaseNovaApiLiveTest {
|
|||
protected Properties setupProperties() {
|
||||
Properties props = super.setupProperties();
|
||||
volumeProvider = setIfTestSystemPropertyPresent(props, provider + ".volume-provider", "openstack-cinder");
|
||||
volumeProviderVersion = setIfTestSystemPropertyPresent(props, provider + ".volume-provider-version",
|
||||
new CinderApiMetadata().getVersion());
|
||||
volumeSizeGB = Integer.parseInt(setIfTestSystemPropertyPresent(props, provider + ".volume-size-gb", "1"));
|
||||
singleRegion = setIfTestSystemPropertyPresent(props, provider + ".region", "RegionOne");
|
||||
return props;
|
||||
|
@ -71,6 +75,7 @@ public class VolumeAttachmentApiLiveTest extends BaseNovaApiLiveTest {
|
|||
if ("openstack-cinder".equals(volumeProvider)) {
|
||||
cinderApi = ContextBuilder.newBuilder(volumeProvider)
|
||||
.endpoint(endpoint)
|
||||
.apiVersion(volumeProviderVersion)
|
||||
.credentials(identity, credential)
|
||||
.buildApi(CinderApi.class);
|
||||
}
|
||||
|
|
|
@ -55,12 +55,10 @@
|
|||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-assistedinject</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.99soft.guice</groupId>
|
||||
|
|
|
@ -206,6 +206,7 @@
|
|||
<maven.site.url.base>gitsite:git@github.com/jclouds/jclouds-maven-site.git</maven.site.url.base>
|
||||
<clojure.version>1.3.0</clojure.version>
|
||||
<guava.version>16.0.1</guava.version>
|
||||
<guice.version>3.0</guice.version>
|
||||
<okhttp.version>2.2.0</okhttp.version>
|
||||
<surefire.version>2.17</surefire.version>
|
||||
<assertj-core.version>1.7.0</assertj-core.version>
|
||||
|
@ -246,6 +247,21 @@
|
|||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-assistedinject</artifactId>
|
||||
<version>${guice.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>${guice.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
<version>${guice.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymockclassextension</artifactId>
|
||||
|
|
|
@ -55,6 +55,11 @@
|
|||
<artifactId>openstack-nova</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- for the extension namespaces -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
|
@ -95,6 +100,12 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds.api</groupId>
|
||||
<artifactId>openstack-cinder</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
|
|
|
@ -26,13 +26,13 @@ import static org.jclouds.openstack.nova.v2_0.config.NovaProperties.AUTO_GENERAT
|
|||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.hpcloud.compute.config.HPCloudComputeHttpApiModule;
|
||||
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.KeystoneAuthenticationModule.RegionModule;
|
||||
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.providers.ProviderMetadata;
|
||||
import org.jclouds.providers.internal.BaseProviderMetadata;
|
||||
|
@ -95,7 +95,7 @@ public class HPCloudComputeProviderMetadata extends BaseProviderMetadata {
|
|||
.add(KeystoneAuthenticationModule.class)
|
||||
.add(RegionModule.class)
|
||||
.add(NovaParserModule.class)
|
||||
.add(NovaHttpApiModule.class)
|
||||
.add(HPCloudComputeHttpApiModule.class)
|
||||
.add(HPCloudComputeServiceContextModule.class).build())
|
||||
.build())
|
||||
.homepage(URI.create("http://hpcloud.com"))
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.hpcloud.compute.config;
|
||||
|
||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneHttpApiModule.aliasBinder;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.openstack.nova.v2_0.config.NovaHttpApiModule;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
|
||||
@ConfiguresHttpApi
|
||||
public class HPCloudComputeHttpApiModule extends NovaHttpApiModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
MapBinder<URI, URI> aliases = aliasBinder(binder());
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.VOLUME_ATTACHMENTS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.hpcloud.compute.extensions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.hpcloud.compute.HPCloudComputeProviderMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAttachmentApiLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "live", testName = "HPCloudComputeVolumeAttachmentExtensionLiveTest", singleThreaded = true)
|
||||
public class HPCloudComputeVolumeAttachmentExtensionLiveTest extends VolumeAttachmentApiLiveTest {
|
||||
|
||||
public HPCloudComputeVolumeAttachmentExtensionLiveTest() {
|
||||
HPCloudComputeProviderMetadata metadata = new HPCloudComputeProviderMetadata();
|
||||
provider = metadata.getId();
|
||||
System.setProperty("test." + provider + ".endpoint", metadata.getEndpoint());
|
||||
System.setProperty(KeystoneProperties.CREDENTIAL_TYPE, CredentialTypes.API_ACCESS_KEY_CREDENTIALS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties props = super.setupProperties();
|
||||
volumeProviderVersion = setIfTestSystemPropertyPresent(props, provider + ".volume-provider-version", "1.0");
|
||||
singleRegion = setIfTestSystemPropertyPresent(props, provider + ".region", "region-a.geo-1");
|
||||
return props;
|
||||
}
|
||||
|
||||
}
|
|
@ -53,6 +53,11 @@
|
|||
<artifactId>openstack-nova</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- for the extension namespaces -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
|
@ -110,6 +115,12 @@
|
|||
<artifactId>auto-service</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds.provider</groupId>
|
||||
<artifactId>rackspace-cloudblockstorage-uk</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.Properties;
|
|||
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
|
||||
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.providers.ProviderMetadata;
|
||||
import org.jclouds.providers.internal.BaseProviderMetadata;
|
||||
|
@ -35,6 +34,7 @@ import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticati
|
|||
import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
|
||||
import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
|
||||
import org.jclouds.rackspace.cloudservers.uk.config.CloudServersUKComputeServiceContextModule;
|
||||
import org.jclouds.rackspace.cloudservers.uk.config.CloudServersUKHttpApiModule;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -89,7 +89,7 @@ public class CloudServersUKProviderMetadata extends BaseProviderMetadata {
|
|||
.add(CloudIdentityAuthenticationModule.class)
|
||||
.add(RegionModule.class)
|
||||
.add(NovaParserModule.class)
|
||||
.add(NovaHttpApiModule.class)
|
||||
.add(CloudServersUKHttpApiModule.class)
|
||||
.add(CloudServersUKComputeServiceContextModule.class).build())
|
||||
.build())
|
||||
.homepage(URI.create("http://www.rackspace.co.uk/opencloud"))
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.rackspace.cloudservers.uk.config;
|
||||
|
||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneHttpApiModule.aliasBinder;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.openstack.nova.v2_0.config.NovaHttpApiModule;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
|
||||
/**
|
||||
* Configures the Rackspace connection.
|
||||
*/
|
||||
@ConfiguresHttpApi
|
||||
public class CloudServersUKHttpApiModule extends NovaHttpApiModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
MapBinder<URI, URI> aliases = aliasBinder(binder());
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.VOLUME_ATTACHMENTS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.rackspace.cloudservers.uk.compute.extensions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAttachmentApiLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "live", singleThreaded = true, testName = "CloudServersUKVolumeAttachmentExtensionLiveTest")
|
||||
public class CloudServersUKVolumeAttachmentExtensionLiveTest extends VolumeAttachmentApiLiveTest {
|
||||
|
||||
public CloudServersUKVolumeAttachmentExtensionLiveTest() {
|
||||
provider = "rackspace-cloudservers-uk";
|
||||
// Specifying a device currently does not work for rackspace and causes issues
|
||||
deviceId = "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties props = super.setupProperties();
|
||||
volumeProvider = "rackspace-cloudblockstorage-uk";
|
||||
volumeSizeGB = 80;
|
||||
singleRegion = "LON";
|
||||
return props;
|
||||
}
|
||||
|
||||
}
|
|
@ -53,6 +53,11 @@
|
|||
<artifactId>openstack-nova</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- for the extension namespaces -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds</groupId>
|
||||
<artifactId>jclouds-core</artifactId>
|
||||
|
|
|
@ -16,109 +16,29 @@
|
|||
*/
|
||||
package org.jclouds.rackspace.cloudservers.us.config;
|
||||
|
||||
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneHttpApiModule.aliasBinder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
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.config.NovaHttpApiModule;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces;
|
||||
import org.jclouds.openstack.nova.v2_0.handlers.NovaErrorHandler;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
|
||||
import org.jclouds.rest.ConfiguresHttpApi;
|
||||
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.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.multibindings.MapBinder;
|
||||
|
||||
/**
|
||||
* Configures the Rackspace connection.
|
||||
*
|
||||
*/
|
||||
@ConfiguresHttpApi
|
||||
public class CloudServersUSHttpApiModule extends HttpApiModule<NovaApi> {
|
||||
|
||||
public CloudServersUSHttpApiModule() {
|
||||
}
|
||||
public class CloudServersUSHttpApiModule extends NovaHttpApiModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
super.configure();
|
||||
MapBinder<URI, URI> aliases = aliasBinder(binder());
|
||||
aliases.addBinding(URI.create(ExtensionNamespaces.VOLUME_ATTACHMENTS)).toInstance(
|
||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public Multimap<URI, URI> aliases() {
|
||||
return ImmutableMultimap.<URI, URI>builder()
|
||||
.put(URI.create(ExtensionNamespaces.SECURITY_GROUPS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/securitygroups/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.FLOATING_IPS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/floating_ips/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.KEYPAIRS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/keypairs/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.SIMPLE_TENANT_USAGE),
|
||||
URI.create("http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.HOSTS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUMES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VIRTUAL_INTERFACES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.CREATESERVEREXT),
|
||||
URI.create("http://docs.openstack.org/compute/ext/createserverext/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.ADMIN_ACTIONS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/admin-actions/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.AGGREGATES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/aggregates/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.FLAVOR_EXTRA_SPECS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/flavor_extra_specs/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.QUOTAS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUME_TYPES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/volume_types/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.AVAILABILITY_ZONE),
|
||||
URI.create("http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1"))
|
||||
/**
|
||||
* Only change - this is to ensure that for rackspace, the extension detection for
|
||||
* VOLUME_ATTACHMENTS is based on discovering this namespace (VOLUMES).
|
||||
*/
|
||||
.put(URI.create(ExtensionNamespaces.VOLUME_ATTACHMENTS),
|
||||
//URI.create("http://docs.openstack.org/compute/ext/os-volume-attachment-update/api/v2"))
|
||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.ATTACH_INTERFACES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/interfaces/api/v1.1"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public LoadingCache<String, Set<? extends Extension>> provideExtensionsByRegion(final Provider<NovaApi> novaApi) {
|
||||
return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS)
|
||||
.build(new CacheLoader<String, Set<? extends Extension>>() {
|
||||
@Override
|
||||
public Set<? extends Extension> load(String key) throws Exception {
|
||||
return novaApi.get().getExtensionApi(key).list();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindErrorHandlers() {
|
||||
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(NovaErrorHandler.class);
|
||||
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(NovaErrorHandler.class);
|
||||
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(NovaErrorHandler.class);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue