mirror of https://github.com/apache/jclouds.git
Adds a rackspace-specific test and a fix for the volume-attach extension problem.
This commit is contained in:
parent
3077a0cc7c
commit
8217248571
|
@ -112,16 +112,9 @@ public class VolumePredicates {
|
|||
@Override
|
||||
public boolean apply(Volume volume) {
|
||||
checkNotNull(volume, "volume must be defined");
|
||||
|
||||
if (status.equals(volume.getStatus())) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
Volume volumeUpdated = volumeApi.get(volume.getId());
|
||||
checkNotNull(volumeUpdated, "Volume %s not found.", volume.getId());
|
||||
|
||||
return status.equals(volumeUpdated.getStatus());
|
||||
}
|
||||
Volume volumeUpdated = volumeApi.get(volume.getId());
|
||||
checkNotNull(volumeUpdated, "Volume %s not found.", volume.getId());
|
||||
return status.equals(volumeUpdated.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,12 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.extensions;
|
||||
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.Iterables;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jclouds.ContextBuilder;
|
||||
import org.jclouds.openstack.cinder.v1.CinderApi;
|
||||
import org.jclouds.openstack.cinder.v1.domain.Volume;
|
||||
|
@ -31,10 +35,7 @@ import org.testng.annotations.AfterClass;
|
|||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
|
||||
/**
|
||||
* Tests behavior of Volume Attachment API
|
||||
|
@ -44,10 +45,22 @@ public class VolumeAttachmentApiLiveTest extends BaseNovaApiLiveTest {
|
|||
private VolumeApi volumeApi;
|
||||
private VolumeAttachmentApi volumeAttachmentApi;
|
||||
|
||||
private String region;
|
||||
private Volume volume;
|
||||
private Server server;
|
||||
|
||||
protected String volumeProvider;
|
||||
protected int volumeSizeGB;
|
||||
protected String deviceId = "/dev/wtf";
|
||||
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties props = super.setupProperties();
|
||||
volumeProvider = setIfTestSystemPropertyPresent(props, provider + ".volume-provider", "openstack-cinder");
|
||||
volumeSizeGB = Integer.parseInt(setIfTestSystemPropertyPresent(props, provider + ".volume-size-gb", "1"));
|
||||
singleRegion = setIfTestSystemPropertyPresent(props, provider + ".region", "RegionOne");
|
||||
return props;
|
||||
}
|
||||
|
||||
@BeforeClass(groups = {"integration", "live"})
|
||||
@Override
|
||||
public void setup() {
|
||||
|
@ -55,67 +68,44 @@ public class VolumeAttachmentApiLiveTest extends BaseNovaApiLiveTest {
|
|||
|
||||
CinderApi cinderApi;
|
||||
|
||||
if ("openstack-cinder".equals(getVolumeProvider())) {
|
||||
cinderApi = ContextBuilder.newBuilder(getVolumeProvider())
|
||||
if ("openstack-cinder".equals(volumeProvider)) {
|
||||
cinderApi = ContextBuilder.newBuilder(volumeProvider)
|
||||
.endpoint(endpoint)
|
||||
.credentials(identity, credential)
|
||||
.buildApi(CinderApi.class);
|
||||
}
|
||||
else {
|
||||
cinderApi = ContextBuilder.newBuilder(getVolumeProvider())
|
||||
cinderApi = ContextBuilder.newBuilder(volumeProvider)
|
||||
.credentials(identity, credential)
|
||||
.buildApi(CinderApi.class);
|
||||
}
|
||||
|
||||
region = Iterables.getFirst(regions, "RegionOne");
|
||||
volumeApi = cinderApi.getVolumeApi(region);
|
||||
volumeAttachmentApi = api.getVolumeAttachmentApi(region).get();
|
||||
volumeApi = cinderApi.getVolumeApi(singleRegion);
|
||||
volumeAttachmentApi = api.getVolumeAttachmentApi(singleRegion).get();
|
||||
|
||||
CreateVolumeOptions options = CreateVolumeOptions.Builder
|
||||
.name("jclouds-test-volume")
|
||||
.description("description of test volume");
|
||||
|
||||
volume = volumeApi.create(getVolumeSizeGB(), options);
|
||||
volume = volumeApi.create(volumeSizeGB, options);
|
||||
VolumePredicates.awaitAvailable(volumeApi).apply(volume);
|
||||
|
||||
server = createServerInRegion(region);
|
||||
server = createServerInRegion(singleRegion);
|
||||
}
|
||||
|
||||
@AfterClass(groups = {"integration", "live"})
|
||||
@Override
|
||||
public void tearDown() {
|
||||
volumeApi.delete(volume.getId());
|
||||
api.getServerApi(region).delete(server.getId());
|
||||
api.getServerApi(singleRegion).delete(server.getId());
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public String getVolumeProvider() {
|
||||
String volumeProviderKey = "test." + provider + ".volume-provider";
|
||||
|
||||
if (System.getProperties().containsKey(volumeProviderKey)) {
|
||||
return System.getProperty(volumeProviderKey);
|
||||
}
|
||||
else {
|
||||
return "openstack-cinder";
|
||||
}
|
||||
}
|
||||
|
||||
public int getVolumeSizeGB() {
|
||||
String volumeSizeKey = "test." + provider + ".volume-size-gb";
|
||||
|
||||
if (System.getProperties().containsKey(volumeSizeKey)) {
|
||||
return Integer.parseInt(System.getProperty(volumeSizeKey));
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachVolume() throws TimeoutException {
|
||||
VolumeAttachment volumeAttachment = volumeAttachmentApi
|
||||
.attachVolumeToServerAsDevice(volume.getId(), server.getId(), "/dev/wtf");
|
||||
.attachVolumeToServerAsDevice(volume.getId(), server.getId(), deviceId);
|
||||
|
||||
// Wait for the volume to become Attached (aka In Use) before moving on
|
||||
if (!VolumePredicates.awaitInUse(volumeApi).apply(volume)) {
|
||||
|
|
|
@ -54,16 +54,15 @@ public class BaseNovaApiLiveTest extends BaseApiLiveTest<NovaApi> {
|
|||
}
|
||||
|
||||
protected Set<String> regions;
|
||||
protected String singleRegion;
|
||||
|
||||
@BeforeClass(groups = { "integration", "live" })
|
||||
@Override
|
||||
public void setup() {
|
||||
super.setup();
|
||||
|
||||
String testRegion = System.getProperty("test." + provider + ".region");
|
||||
|
||||
if (testRegion != null) {
|
||||
regions = ImmutableSet.of(testRegion);
|
||||
if (singleRegion != null) {
|
||||
regions = ImmutableSet.of(singleRegion);
|
||||
} else {
|
||||
regions = api.getConfiguredRegions();
|
||||
}
|
||||
|
@ -82,6 +81,7 @@ public class BaseNovaApiLiveTest extends BaseApiLiveTest<NovaApi> {
|
|||
Properties props = super.setupProperties();
|
||||
setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE);
|
||||
setIfTestSystemPropertyPresent(props, NovaProperties.AUTO_ALLOCATE_FLOATING_IPS);
|
||||
singleRegion = setIfTestSystemPropertyPresent(props, provider + ".region");
|
||||
return props;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,17 @@ public abstract class BaseApiLiveTest<A extends Closeable> {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected String setIfTestSystemPropertyPresent(Properties overrides, String key, String defaultValue) {
|
||||
String val = setIfTestSystemPropertyPresent(overrides, key);
|
||||
|
||||
if (val == null) {
|
||||
val = defaultValue;
|
||||
overrides.setProperty(key, val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* This helps live testing against specific regions only.
|
||||
* @param regions A list of regions, usually from getConfiguredRegions()
|
||||
|
|
|
@ -110,6 +110,12 @@
|
|||
<artifactId>auto-service</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jclouds.provider</groupId>
|
||||
<artifactId>rackspace-cloudblockstorage-us</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.us.config.CloudServersUSComputeServiceContextModule;
|
||||
import org.jclouds.rackspace.cloudservers.us.config.CloudServersUSHttpApiModule;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -87,14 +87,15 @@ public class CloudServersUSProviderMetadata extends BaseProviderMetadata {
|
|||
.version("2")
|
||||
.defaultEndpoint("https://identity.api.rackspacecloud.com/v2.0/")
|
||||
.endpointName("identity service url ending in /v2.0/")
|
||||
.documentation(URI.create("http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/index.html"))
|
||||
.documentation(
|
||||
URI.create("http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/index.html"))
|
||||
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
||||
.add(CloudIdentityAuthenticationApiModule.class)
|
||||
.add(CloudIdentityAuthenticationModule.class)
|
||||
.add(RegionModule.class)
|
||||
.add(NovaParserModule.class)
|
||||
.add(NovaHttpApiModule.class)
|
||||
.add(CloudServersUSComputeServiceContextModule.class).build())
|
||||
.add(CloudIdentityAuthenticationApiModule.class)
|
||||
.add(CloudIdentityAuthenticationModule.class)
|
||||
.add(RegionModule.class)
|
||||
.add(NovaParserModule.class)
|
||||
.add(CloudServersUSHttpApiModule.class)
|
||||
.add(CloudServersUSComputeServiceContextModule.class).build())
|
||||
.build())
|
||||
.homepage(URI.create("http://www.rackspace.com/cloud/nextgen"))
|
||||
.console(URI.create("https://mycloud.rackspace.com"))
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* 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.us.config;
|
||||
|
||||
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.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;
|
||||
|
||||
/**
|
||||
* Configures the Rackspace connection.
|
||||
*
|
||||
*/
|
||||
@ConfiguresHttpApi
|
||||
public class CloudServersUSHttpApiModule extends HttpApiModule<NovaApi> {
|
||||
|
||||
public CloudServersUSHttpApiModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
|
@ -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.us.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 = "CloudServersUSVolumeAttachmentExtensionLivetest")
|
||||
public class CloudServersUSVolumeAttachmentExtensionLiveTest extends VolumeAttachmentApiLiveTest {
|
||||
|
||||
public CloudServersUSVolumeAttachmentExtensionLiveTest() {
|
||||
provider = "rackspace-cloudservers-us";
|
||||
// Specifying a device currently does not work for rackspace and causes issues
|
||||
deviceId = "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Properties setupProperties() {
|
||||
Properties props = super.setupProperties();
|
||||
volumeProvider = "rackspace-cloudblockstorage-us";
|
||||
volumeSizeGB = 80;
|
||||
singleRegion = "IAD";
|
||||
return props;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue