Issue 814: changes needed to be compatible with trystack

This commit is contained in:
Adrian Cole 2012-03-22 21:37:21 -07:00
parent 4ccd20e660
commit 91661f4759
19 changed files with 746 additions and 47 deletions

View File

@ -0,0 +1,49 @@
{
"access": {
"token": {
"expires": "2012-03-23T21:44:09",
"id": "Auth_4f173437e4b013bee56d1007",
"tenant": {
"id": "3456",
"name": "508151008"
}
},
"serviceCatalog": [{
"endpoints": [{
"adminURL": "https://nova-api.trystack.org:9774/v1.1/3456",
"region": "RegionOne",
"internalURL": "https://nova-api.trystack.org:9774/v1.1/3456",
"publicURL": "https://nova-api.trystack.org:9774/v1.1/3456"
}],
"type": "compute",
"name": "nova"
}, {
"endpoints": [{
"adminURL": "https://GLANCE_API_IS_NOT_DISCLOSED/v1.1/3456",
"region": "RegionOne",
"internalURL": "https://GLANCE_API_IS_NOT_DISCLOSED/v1.1/3456",
"publicURL": "https://GLANCE_API_IS_NOT_DISCLOSED/v1.1/3456"
}],
"type": "image",
"name": "glance"
}, {
"endpoints": [{
"adminURL": "https://nova-api.trystack.org:5443/v2.0",
"region": "RegionOne",
"internalURL": "https://keystone.thefreecloud.org:5000/v2.0",
"publicURL": "https://keystone.thefreecloud.org:5000/v2.0"
}],
"type": "identity",
"name": "keystone"
}],
"user": {
"id": "43",
"roles": [{
"tenantId": "3456",
"id": "2",
"name": "Member"
}],
"name": "508151008"
}
}
}

View File

@ -109,7 +109,7 @@ public class NovaComputeServiceContextModule
bind(new TypeLiteral<Function<ImageInZone, Image>>() { bind(new TypeLiteral<Function<ImageInZone, Image>>() {
}).to(ImageInZoneToImage.class); }).to(ImageInZoneToImage.class);
bind(new TypeLiteral<Function<org.jclouds.openstack.nova.v1_1.domain.Image, OperatingSystem>>() { bind(new TypeLiteral<Function<org.jclouds.openstack.nova.v1_1.domain.Image, OperatingSystem>>() {
}).to(NovaImageToOperatingSystem.class); }).to(ImageToOperatingSystem.class);
bind(new TypeLiteral<Function<FlavorInZone, Hardware>>() { bind(new TypeLiteral<Function<FlavorInZone, Hardware>>() {
}).to(FlavorInZoneToHardware.class); }).to(FlavorInZoneToHardware.class);

View File

@ -86,14 +86,11 @@ public class CreateSecurityGroupIfNeeded implements Function<ZoneSecurityGroupNa
private void authorizeGroupToItselfAndAllIPsToTCPPort(SecurityGroupClient securityGroupClient, private void authorizeGroupToItselfAndAllIPsToTCPPort(SecurityGroupClient securityGroupClient,
SecurityGroup securityGroup, int port) { SecurityGroup securityGroup, int port) {
logger.debug(">> authorizing securityGroup(%s) permission to port %d", securityGroup, port); // NOTE that permission to itself isn't supported on trystack!
logger.trace(">> authorizing securityGroup(%s) permission to itself on port %d", securityGroup, port); logger.debug(">> authorizing securityGroup(%s) permission to 0.0.0.0/0 on port %d", securityGroup, port);
securityGroupClient.createSecurityGroupRuleAllowingSecurityGroupId(securityGroup.getId(), Ingress.builder()
.ipProtocol(IpProtocol.TCP).fromPort(port).toPort(port).build(), securityGroup.getId());
logger.trace(">> authorizing securityGroup(%s) permission to 0.0.0.0/0 on port %d", securityGroup, port);
securityGroupClient.createSecurityGroupRuleAllowingCidrBlock(securityGroup.getId(), Ingress.builder().ipProtocol( securityGroupClient.createSecurityGroupRuleAllowingCidrBlock(securityGroup.getId(), Ingress.builder().ipProtocol(
IpProtocol.TCP).fromPort(port).toPort(port).build(), "0.0.0.0/0"); IpProtocol.TCP).fromPort(port).toPort(port).build(), "0.0.0.0/0");
logger.debug("<< authorized securityGroup(%s) permission to port %d", securityGroup, port); logger.debug("<< authorized securityGroup(%s) permission to 0.0.0.0/0 on port %d", securityGroup, port);
} }
} }

View File

@ -18,8 +18,16 @@
*/ */
package org.jclouds.openstack.nova.v1_1.compute.functions; package org.jclouds.openstack.nova.v1_1.compute.functions;
import static com.google.common.base.Predicates.containsPattern;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -38,17 +46,14 @@ import com.google.common.base.CharMatcher;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
/** /**
* A function for transforming a nova specific Image into a generic * A function for transforming a nova specific Image into a generic OperatingSystem object.
* OperatingSystem object.
* *
* @author Matt Stephenson * @author Matt Stephenson
*/ */
public class NovaImageToOperatingSystem implements Function<Image, OperatingSystem> { public class ImageToOperatingSystem implements Function<Image, OperatingSystem> {
public static final Pattern DEFAULT_PATTERN = Pattern.compile("(([^ ]*) ([0-9.]+) ?.*)"); public static final Pattern DEFAULT_PATTERN = Pattern.compile("(([^ ]*) ([0-9.]+) ?.*)");
// Windows Server 2008 R2 x64 // Windows Server 2008 R2 x64
public static final Pattern WINDOWS_PATTERN = Pattern.compile("Windows (.*) (x[86][64])"); public static final Pattern WINDOWS_PATTERN = Pattern.compile("Windows (.*) (x[86][64])");
@ -60,7 +65,7 @@ public class NovaImageToOperatingSystem implements Function<Image, OperatingSyst
private final Map<OsFamily, Map<String, String>> osVersionMap; private final Map<OsFamily, Map<String, String>> osVersionMap;
@Inject @Inject
public NovaImageToOperatingSystem(Map<OsFamily, Map<String, String>> osVersionMap) { public ImageToOperatingSystem(Map<OsFamily, Map<String, String>> osVersionMap) {
this.osVersionMap = osVersionMap; this.osVersionMap = osVersionMap;
} }
@ -85,15 +90,26 @@ public class NovaImageToOperatingSystem implements Function<Image, OperatingSyst
} else if (imageName.contains("Oracle EL")) { } else if (imageName.contains("Oracle EL")) {
osFamily = OsFamily.OEL; osFamily = OsFamily.OEL;
} else { } else {
final Iterable<String> imageNameParts = Splitter.on(CharMatcher.WHITESPACE).trimResults() final Iterable<String> imageNameParts = Splitter.on(CharMatcher.WHITESPACE).trimResults().split(
.split(imageName.toLowerCase()); imageName.toLowerCase());
osFamily = Iterables.find(Arrays.asList(OsFamily.values()), new Predicate<OsFamily>() { try {
@Override osFamily = find(Arrays.asList(OsFamily.values()), new Predicate<OsFamily>() {
public boolean apply(@Nullable OsFamily osFamily) { @Override
return Iterables.any(imageNameParts, Predicates.equalTo(osFamily.name().toLowerCase())); public boolean apply(@Nullable OsFamily osFamily) {
return any(imageNameParts, equalTo(osFamily.name().toLowerCase()));
}
});
} catch (NoSuchElementException e) {
String ubuntuVersion = startsWithUbuntuVersion(imageNameParts);
if (ubuntuVersion != null) {
osFamily = OsFamily.UBUNTU;
osVersion = ubuntuVersion;
} else {
logger.trace("could not parse operating system family for image(%s): %s", imageNameParts);
osFamily = OsFamily.UNRECOGNIZED;
} }
}); }
} }
Matcher matcher = DEFAULT_PATTERN.matcher(imageName); Matcher matcher = DEFAULT_PATTERN.matcher(imageName);
if (matcher.find() && matcher.groupCount() >= 3) { if (matcher.find() && matcher.groupCount() >= 3) {
@ -102,4 +118,14 @@ public class NovaImageToOperatingSystem implements Function<Image, OperatingSyst
} }
return new OperatingSystem(osFamily, imageName, osVersion, null, imageName, is64Bit); return new OperatingSystem(osFamily, imageName, osVersion, null, imageName, is64Bit);
} }
String startsWithUbuntuVersion(final Iterable<String> imageNameParts) {
Map<String, String> ubuntuVersions = osVersionMap.get(OsFamily.UBUNTU);
for (String ubuntuKey : filter(ubuntuVersions.keySet(), not(equalTo("")))) {
if (any(imageNameParts, containsPattern("^" + ubuntuKey + ".*"))) {
return ubuntuVersions.get(ubuntuKey);
}
}
return null;
}
} }

View File

@ -20,6 +20,7 @@ package org.jclouds.openstack.nova.v1_1.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
@ -97,7 +98,7 @@ public class ServerInZoneToNodeMetadata implements Function<ServerInZone, NodeMe
builder.operatingSystem(findOperatingSystemForServerOrNull(serverInZone)); builder.operatingSystem(findOperatingSystemForServerOrNull(serverInZone));
builder.hardware(findHardwareForServerOrNull(serverInZone)); builder.hardware(findHardwareForServerOrNull(serverInZone));
builder.state(from.getStatus().getNodeState()); builder.state(from.getStatus().getNodeState());
builder.publicAddresses(filter(transform(from.getPublicAddresses(), builder.publicAddresses(filter(transform(concat(from.getPublicAddresses(), from.getInternetAddresses()),
AddressToStringTransformationFunction.INSTANCE), isInet4Address)); AddressToStringTransformationFunction.INSTANCE), isInet4Address));
builder.privateAddresses(filter(transform(from.getPrivateAddresses(), builder.privateAddresses(filter(transform(from.getPrivateAddresses(),
AddressToStringTransformationFunction.INSTANCE), isInet4Address)); AddressToStringTransformationFunction.INSTANCE), isInet4Address));

View File

@ -35,6 +35,10 @@ public class Address {
* Relations associated with resources. * Relations associated with resources.
*/ */
public static enum Type { public static enum Type {
/**
* internet routable address
*/
INTERNET,
/** /**
* publically routable address * publically routable address
*/ */

View File

@ -255,6 +255,22 @@ public class Server extends Resource {
return this; return this;
} }
/**
* @see Server#getInternetAddresses()
*/
public Builder internetAddresses(Address... internetAddresses) {
return internetAddresses(ImmutableSet.copyOf(checkNotNull(internetAddresses, "internetAddresses")));
}
/**
* @see Server#getInternetAddresses()
*/
public Builder internetAddresses(Set<Address> internetAddresses) {
this.addresses.replaceValues(Address.Type.INTERNET, ImmutableSet.copyOf(checkNotNull(internetAddresses,
"internetAddresses")));
return this;
}
/** /**
* @see Server#getPublicAddresses() * @see Server#getPublicAddresses()
*/ */
@ -467,6 +483,19 @@ public class Server extends Resource {
} }
} }
/**
* @return the internet ip addresses assigned to the server
* @since essex
*/
public Set<Address> getInternetAddresses() {
Collection<Address> internetAddrs = getAddresses().get(Address.Type.INTERNET);
if (internetAddrs == null) {
return ImmutableSet.<Address> of();
} else {
return ImmutableSet.copyOf(internetAddrs);
}
}
/** /**
* @return the public ip addresses assigned to the server * @return the public ip addresses assigned to the server
*/ */

View File

@ -25,8 +25,65 @@ package org.jclouds.openstack.nova.v1_1.extensions;
* @see <a href= "http://nova.openstack.org/api_ext/" /> * @see <a href= "http://nova.openstack.org/api_ext/" />
*/ */
public interface ExtensionNamespaces { public interface ExtensionNamespaces {
/**
* Keypair Support
*/
public static final String KEYPAIRS = "http://docs.openstack.org/ext/keypairs/api/v1.1"; public static final String KEYPAIRS = "http://docs.openstack.org/ext/keypairs/api/v1.1";
/**
* Volumes support
*/
public static final String VOLUMES = "http://docs.openstack.org/ext/volumes/api/v1.1"; public static final String VOLUMES = "http://docs.openstack.org/ext/volumes/api/v1.1";
/**
* Volume types support
*/
public static final String VOLUME_TYPES = "http://docs.openstack.org/ext/volume_types/api/v1.1";
/**
* Security group support
*/
public static final String SECURITY_GROUPS = "http://docs.openstack.org/ext/securitygroups/api/v1.1"; public static final String SECURITY_GROUPS = "http://docs.openstack.org/ext/securitygroups/api/v1.1";
/**
* Floating IPs support
*/
public static final String FLOATING_IPS = "http://docs.openstack.org/ext/floating_ips/api/v1.1"; public static final String FLOATING_IPS = "http://docs.openstack.org/ext/floating_ips/api/v1.1";
/**
* Multiple network support
*/
public static final String MULTINIC = "http://docs.openstack.org/ext/multinic/api/v1.1";
/**
* Host administration
*/
public static final String HOSTS = "http://docs.openstack.org/ext/hosts/api/v1.1";
/**
* Quotas management support
*/
public static final String QUOTAS = "http://docs.openstack.org/ext/quotas-sets/api/v1.1";
/**
* Instance type (flavor) extra specs
*/
public static final String FLAVOR_EXTRA_SPECS = "http://docs.openstack.org/ext/flavor_extra_specs/api/v1.1";
/**
* Provide additional data for flavors
*/
public static final String FLAVOR_EXTRA_DATA = "http://docs.openstack.org/ext/flavor_extra_data/api/v1.1";
/**
* Virtual interface support
*/
public static final String VIRTUAL_INTERFACES = "http://docs.openstack.org/ext/virtual_interfaces/api/v1.1";
/**
* Extended support to the Create Server v1.1 API
*/
public static final String CREATESERVEREXT = "http://docs.openstack.org/ext/createserverext/api/v1.1";
/**
* Virtual Storage Arrays support
*/
public static final String VSA = "http://docs.openstack.org/ext/vsa/api/v1.1";
/**
* Simple tenant usage extension
*/
public static final String SIMPLE_TENANT_USAGE = "http://docs.openstack.org/ext/os-simple-tenant-usage/api/v1.1";
/**
* Instance rescue mode
*/
public static final String RESCUE = "http://docs.openstack.org/ext/rescue/api/v1.1";
} }

View File

@ -20,7 +20,10 @@ package org.jclouds.openstack.nova.v1_1.functions;
import java.net.URI; import java.net.URI;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.ws.rs.core.UriBuilder;
import org.jclouds.openstack.nova.v1_1.domain.Extension; import org.jclouds.openstack.nova.v1_1.domain.Extension;
@ -28,10 +31,16 @@ import com.google.common.base.Function;
@Singleton @Singleton
public class ExtensionToNameSpace implements Function<Extension, URI> { public class ExtensionToNameSpace implements Function<Extension, URI> {
private final Provider<UriBuilder> uriBuilders;
@Inject
public ExtensionToNameSpace(Provider<UriBuilder> uriBuilders) {
this.uriBuilders = uriBuilders;
}
@Override @Override
public URI apply(Extension input) { public URI apply(Extension input) {
return input.getNamespace(); return uriBuilders.get().uri(input.getNamespace()).scheme("http").build();
} }
public String toString() { public String toString() {

View File

@ -47,7 +47,7 @@ public class ExtensionPredicates {
return new Predicate<Extension>() { return new Predicate<Extension>() {
@Override @Override
public boolean apply(Extension ext) { public boolean apply(Extension ext) {
return namespace.equals(ext.getNamespace()); return namespace.toASCIIString().equals(ext.getNamespace().toASCIIString().replace("https", "http"));
} }
@Override @Override

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.openstack.nova.v1_1.compute; package org.jclouds.openstack.nova.v1_1.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
@ -26,18 +27,18 @@ import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaComputeServiceExpectTest; import org.jclouds.openstack.nova.v1_1.internal.BaseNovaComputeServiceExpectTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Iterables;
/** /**
* Tests the compute service abstraction of the nova client. * Tests the compute service abstraction of the nova client.
@ -47,13 +48,12 @@ import com.google.common.collect.ImmutableMultimap;
@Test(groups = "unit", testName = "NovaComputeServiceExpectTest") @Test(groups = "unit", testName = "NovaComputeServiceExpectTest")
public class NovaComputeServiceExpectTest extends BaseNovaComputeServiceExpectTest { public class NovaComputeServiceExpectTest extends BaseNovaComputeServiceExpectTest {
public void testListServersWhenResponseIs2xx() throws Exception { public void testListLocationsWhenResponseIs2xx() throws Exception {
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder().put( Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder().put(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess).put(extensionsOfNovaRequest, keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess).put(extensionsOfNovaRequest,
extensionsOfNovaResponse).put(listImagesDetail, listImagesDetailResponse).put(listServers, extensionsOfNovaResponse).put(listImagesDetail, listImagesDetailResponse).put(listServers,
listServersResponse).put(listFlavorsDetail, listFlavorsDetailResponse).put(listFloatingIps, listServersResponse).put(listFlavorsDetail, listFlavorsDetailResponse).build();
listFloatingIpsResponse).build();
ComputeService clientWhenServersExist = requestsSendResponses(requestResponseMap); ComputeService clientWhenServersExist = requestsSendResponses(requestResponseMap);
@ -69,6 +69,46 @@ public class NovaComputeServiceExpectTest extends BaseNovaComputeServiceExpectTe
assertEquals(clientWhenServersExist.listNodes().iterator().next().getName(), "sample-server"); assertEquals(clientWhenServersExist.listNodes().iterator().next().getName(), "sample-server");
} }
public void testDefaultTemplateTryStack() throws Exception {
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder().put(
keystoneAuthWithAccessKeyAndSecretKey,
HttpResponse.builder().statusCode(200).message("HTTP/1.1 200").payload(
payloadFromResourceWithContentType("/keystoneAuthResponse_trystack.json", "application/json"))
.build()).put(
extensionsOfNovaRequest.toBuilder().endpoint(
URI.create("https://nova-api.trystack.org:9774/v1.1/3456/extensions")).build(),
HttpResponse.builder().statusCode(200).payload(payloadFromResource("/extension_list_trystack.json"))
.build()).put(
listImagesDetail.toBuilder().endpoint(
URI.create("https://nova-api.trystack.org:9774/v1.1/3456/images/detail")).build(),
HttpResponse.builder().statusCode(200).payload(payloadFromResource("/image_list_detail_trystack.json"))
.build()).put(
listServers.toBuilder().endpoint(
URI.create("https://nova-api.trystack.org:9774/v1.1/3456/servers/detail")).build(),
listServersResponse).put(
listFlavorsDetail.toBuilder().endpoint(
URI.create("https://nova-api.trystack.org:9774/v1.1/3456/flavors/detail")).build(),
HttpResponse.builder().statusCode(200).payload(payloadFromResource("/flavor_list_detail_trystack.json"))
.build()).build();
ComputeService clientForTryStack = requestsSendResponses(requestResponseMap);
Template defaultTemplate = clientForTryStack.templateBuilder().imageId("RegionOne/15").build();
checkTemplate(defaultTemplate);
checkTemplate(clientForTryStack.templateBuilder().fromTemplate(defaultTemplate).build());
}
private void checkTemplate(Template defaultTemplate) {
assertEquals(defaultTemplate.getImage().getId(), "RegionOne/15");
assertEquals(defaultTemplate.getImage().getProviderId(), "15");
assertEquals(defaultTemplate.getHardware().getId(), "RegionOne/1");
assertEquals(defaultTemplate.getHardware().getProviderId(), "1");
assertEquals(defaultTemplate.getLocation().getId(), "RegionOne");
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
public void testListServersWhenReponseIs404IsEmpty() throws Exception { public void testListServersWhenReponseIs404IsEmpty() throws Exception {
HttpRequest listServers = HttpRequest.builder().method("GET").endpoint( HttpRequest listServers = HttpRequest.builder().method("GET").endpoint(
URI.create("https://compute.north.host/v1.1/3456/servers/detail")).headers( URI.create("https://compute.north.host/v1.1/3456/servers/detail")).headers(
@ -89,8 +129,7 @@ public class NovaComputeServiceExpectTest extends BaseNovaComputeServiceExpectTe
Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder().put( Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder().put(
keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess).put(extensionsOfNovaRequest, keystoneAuthWithAccessKeyAndSecretKey, responseWithKeystoneAccess).put(extensionsOfNovaRequest,
extensionsOfNovaResponse).put(listImagesDetail, listImagesDetailResponse).put(listServers, extensionsOfNovaResponse).put(listImagesDetail, listImagesDetailResponse).put(listServers,
listServersResponse).put(listFlavorsDetail, listFlavorsDetailResponse).put(listFloatingIps, listServersResponse).put(listFlavorsDetail, listFlavorsDetailResponse).build();
listFloatingIpsResponse).build();
ComputeService clientThatCreatesNode = requestsSendResponses(requestResponseMap); ComputeService clientThatCreatesNode = requestsSendResponses(requestResponseMap);

View File

@ -44,14 +44,14 @@ import com.google.common.collect.Iterables;
* *
* @author Matt Stephenson * @author Matt Stephenson
*/ */
public class NovaImageToOperatingSystemTest { public class ImageToOperatingSystemTest {
@Test(dataProvider = "getOsFamilyValues") @Test(dataProvider = "getOsFamilyValues")
public void testOsFamilyValues(OsFamily family) { public void testOsFamilyValues(OsFamily family) {
Image imageToConvert = Image.builder().id("id-" + family.name()).name(family.name()).build(); Image imageToConvert = Image.builder().id("id-" + family.name()).name(family.name()).build();
NovaImageToOperatingSystem converter = new NovaImageToOperatingSystem( ImageToOperatingSystem converter = new ImageToOperatingSystem(
new HashMap<OsFamily, Map<String, String>>()); new HashMap<OsFamily, Map<String, String>>());
OperatingSystem convertedOs = converter.apply(imageToConvert); OperatingSystem convertedOs = converter.apply(imageToConvert);
@ -84,7 +84,7 @@ public class NovaImageToOperatingSystemTest {
Map<OsFamily, Map<String, String>> osFamilyMap = new HashMap<OsFamily, Map<String, String>>(); Map<OsFamily, Map<String, String>> osFamilyMap = new HashMap<OsFamily, Map<String, String>>();
osFamilyMap.put(OsFamily.WINDOWS, ImmutableMap.of("Server 2008 R2", "Server-2008-R2")); osFamilyMap.put(OsFamily.WINDOWS, ImmutableMap.of("Server 2008 R2", "Server-2008-R2"));
NovaImageToOperatingSystem converter = new NovaImageToOperatingSystem(osFamilyMap); ImageToOperatingSystem converter = new ImageToOperatingSystem(osFamilyMap);
OperatingSystem convertedOs = converter.apply(imageToConvert); OperatingSystem convertedOs = converter.apply(imageToConvert);
@ -105,7 +105,7 @@ public class NovaImageToOperatingSystemTest {
Map<OsFamily, Map<String, String>> osFamilyMap = new HashMap<OsFamily, Map<String, String>>(); Map<OsFamily, Map<String, String>> osFamilyMap = new HashMap<OsFamily, Map<String, String>>();
osFamilyMap.put(OsFamily.WINDOWS, ImmutableMap.of("98", "98")); osFamilyMap.put(OsFamily.WINDOWS, ImmutableMap.of("98", "98"));
NovaImageToOperatingSystem converter = new NovaImageToOperatingSystem(osFamilyMap); ImageToOperatingSystem converter = new ImageToOperatingSystem(osFamilyMap);
OperatingSystem convertedOs = converter.apply(imageToConvert); OperatingSystem convertedOs = converter.apply(imageToConvert);
@ -123,7 +123,7 @@ public class NovaImageToOperatingSystemTest {
Image imageToConvert = Image.builder().id("id-" + name).name(name).build(); Image imageToConvert = Image.builder().id("id-" + name).name(name).build();
NovaImageToOperatingSystem converter = new NovaImageToOperatingSystem( ImageToOperatingSystem converter = new ImageToOperatingSystem(
new HashMap<OsFamily, Map<String, String>>()); new HashMap<OsFamily, Map<String, String>>());
OperatingSystem convertedOs = converter.apply(imageToConvert); OperatingSystem convertedOs = converter.apply(imageToConvert);
@ -142,7 +142,7 @@ public class NovaImageToOperatingSystemTest {
Image imageToConvert = Image.builder().id("id-" + name).name(name).build(); Image imageToConvert = Image.builder().id("id-" + name).name(name).build();
NovaImageToOperatingSystem converter = new NovaImageToOperatingSystem( ImageToOperatingSystem converter = new ImageToOperatingSystem(
new HashMap<OsFamily, Map<String, String>>()); new HashMap<OsFamily, Map<String, String>>());
OperatingSystem convertedOs = converter.apply(imageToConvert); OperatingSystem convertedOs = converter.apply(imageToConvert);
@ -154,4 +154,42 @@ public class NovaImageToOperatingSystemTest {
assertEquals(convertedOs.getArch(), null); assertEquals(convertedOs.getArch(), null);
assertTrue(convertedOs.is64Bit()); assertTrue(convertedOs.is64Bit());
} }
ImageToOperatingSystem converterForUbuntu = new ImageToOperatingSystem(ImmutableMap.<OsFamily, Map<String, String>> of(
OsFamily.UBUNTU, ImmutableMap.of("lucid", "10.04", "maverick", "10.10", "natty", "11.04", "oneiric",
"11.10")));
@Test
public void testTryStackOneric() {
String name = "oneiric-server-cloudimg-amd64";
Image imageToConvert = Image.builder().id("id-" + name).name(name).build();
OperatingSystem convertedOs = converterForUbuntu.apply(imageToConvert);
assertEquals(convertedOs.getName(), imageToConvert.getName());
assertEquals(convertedOs.getFamily(), OsFamily.UBUNTU);
assertEquals(convertedOs.getDescription(), imageToConvert.getName());
assertEquals(convertedOs.getVersion(), "11.10");
assertEquals(convertedOs.getArch(), null);
assertTrue(convertedOs.is64Bit());
}
@Test
public void testTryStackNatty() {
String name = "natty-server-cloudimg-amd64";
Image imageToConvert = Image.builder().id("id-" + name).name(name).build();
OperatingSystem convertedOs = converterForUbuntu.apply(imageToConvert);
assertEquals(convertedOs.getName(), imageToConvert.getName());
assertEquals(convertedOs.getFamily(), OsFamily.UBUNTU);
assertEquals(convertedOs.getDescription(), imageToConvert.getName());
assertEquals(convertedOs.getVersion(), "11.04");
assertEquals(convertedOs.getArch(), null);
assertTrue(convertedOs.is64Bit());
}
} }

View File

@ -4,22 +4,41 @@ import static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;
import javax.inject.Provider;
import javax.ws.rs.core.UriBuilder;
import org.jclouds.date.internal.SimpleDateFormatDateService; import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.openstack.nova.v1_1.domain.Extension; import org.jclouds.openstack.nova.v1_1.domain.Extension;
import org.jclouds.openstack.nova.v1_1.extensions.ExtensionNamespaces;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.sun.jersey.api.uri.UriBuilderImpl;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "ExtensionToNameSpaceTest") @Test(groups = "unit", testName = "ExtensionToNameSpaceTest")
public class ExtensionToNameSpaceTest { public class ExtensionToNameSpaceTest {
private final ExtensionToNameSpace fn = new ExtensionToNameSpace(); private final ExtensionToNameSpace fn = new ExtensionToNameSpace(new Provider<UriBuilder>() {
@Override
public UriBuilder get() {
return new UriBuilderImpl();
}
});
public void testReturnsNamespace() { public void testReturnsNamespace() {
URI ns = URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1"); URI ns = URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1");
assertEquals( assertEquals(fn.apply(Extension.builder().alias("os-keypairs").name("Keypairs").namespace(ns).updated(
fn.apply(Extension.builder().alias("os-keypairs").name("Keypairs").namespace(ns) new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-08-08T00:00:00+00:00")).description(
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-08-08T00:00:00+00:00")) "Keypair Support").build()), ns);
.description("Keypair Support").build()), ns); }
public void testChangesHttpsToHttp() {
assertEquals(fn.apply(Extension.builder().alias("security_groups").name("SecurityGroups").namespace(
URI.create("https://docs.openstack.org/ext/securitygroups/api/v1.1")).updated(
new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-07-21T00:00:00+00:00")).description(
"Security group support").build()), URI.create(ExtensionNamespaces.SECURITY_GROUPS));
} }
} }

View File

@ -0,0 +1,100 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.v1_1.parse;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.domain.Resource;
import org.jclouds.openstack.domain.Link.Relation;
import org.jclouds.openstack.nova.v1_1.config.NovaParserModule;
import org.jclouds.openstack.nova.v1_1.domain.Address;
import org.jclouds.openstack.nova.v1_1.domain.Server;
import org.jclouds.openstack.nova.v1_1.domain.Server.Status;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseServerTest")
public class ParseServerWithInternetAddressesTest extends BaseItemParserTest<Server> {
@Override
public String resource() {
return "/server_details_trystack.json";
}
@Override
@SelectJson("server")
@Consumes(MediaType.APPLICATION_JSON)
public Server expected() {
return Server
.builder()
.id("1459")
.uuid("2443c9c7-9791-412e-ac09-a6d55ec25335")
.tenantId("37")
.userId("508151008")
.name("mygroup-72c")
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-03-23T01:30:26Z"))
.created(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-03-23T01:30:26Z"))
.hostId("881706597197955ac7cc4b353bc7ec884e13fa280de9cc82057796cb")
.status(Status.ACTIVE)
.image(
Resource
.builder()
.id("14")
.links(
Link.create(
Relation.BOOKMARK,
URI.create("https://nova-api.trystack.org:9774/37/images/14")))
.build())
.flavor(
Resource
.builder()
.id("1")
.links(
Link.create(
Relation.BOOKMARK,
URI.create("https://nova-api.trystack.org:9774/37/flavors/1")))
.build())
.links(
Link.create(
Relation.SELF,
URI.create("https://nova-api.trystack.org:9774/v1.1/37/servers/1459")),
Link.create(
Relation.BOOKMARK,
URI.create("https://nova-api.trystack.org:9774/37/servers/1459")))
.internetAddresses(Address.createV4("8.21.28.47")).build();
}
protected Injector injector() {
return Guice.createInjector(new NovaParserModule(), new GsonModule());
}
}

View File

@ -33,10 +33,10 @@ import org.testng.annotations.Test;
*/ */
@Test(groups = "unit", testName = "ExtensionPredicatesTest") @Test(groups = "unit", testName = "ExtensionPredicatesTest")
public class ExtensionPredicatesTest { public class ExtensionPredicatesTest {
Extension ref = Extension.builder().alias("os-keypairs").name("Keypairs") Extension ref = Extension.builder().alias("os-keypairs").name("Keypairs").namespace(
.namespace(URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")) URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).updated(
.updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-08-08T00:00:00+00:00")) new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-08-08T00:00:00+00:00")).description(
.description("Keypair Support").build(); "Keypair Support").build();
@Test @Test
public void testAliasEqualsWhenEqual() { public void testAliasEqualsWhenEqual() {
@ -53,6 +53,12 @@ public class ExtensionPredicatesTest {
assert namespaceEquals(URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).apply(ref); assert namespaceEquals(URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).apply(ref);
} }
@Test
public void testNamespaceEqualsWhenEqualEvenOnInputHttps() {
assert namespaceEquals(URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).apply(
ref.toBuilder().namespace(URI.create("https://docs.openstack.org/ext/keypairs/api/v1.1")).build());
}
@Test @Test
public void testNamespaceEqualsWhenNotEqual() { public void testNamespaceEqualsWhenNotEqual() {
assert !namespaceEquals(URI.create("foo")).apply(ref); assert !namespaceEquals(URI.create("foo")).apply(ref);

View File

@ -0,0 +1,115 @@
{
"extensions": [{
"updated": "2011-06-09T00:00:00+00:00",
"name": "Multinic",
"links": [],
"namespace": "https://docs.openstack.org/ext/multinic/api/v1.1",
"alias": "NMN",
"description": "Multiple network support"
}, {
"updated": "2011-06-29T00:00:00+00:00",
"name": "Hosts",
"links": [],
"namespace": "https://docs.openstack.org/ext/hosts/api/v1.1",
"alias": "os-hosts",
"description": "Host administration"
}, {
"updated": "2011-03-25T00:00:00+00:00",
"name": "Volumes",
"links": [],
"namespace": "https://docs.openstack.org/ext/volumes/api/v1.1",
"alias": "os-volumes",
"description": "Volumes support"
}, {
"updated": "2011-05-25 16:12:21.656723",
"name": "Admin Controller",
"links": [],
"namespace": "https:TODO/",
"alias": "ADMIN",
"description": "The Admin API Extension"
}, {
"updated": "2011-08-08T00:00:00+00:00",
"name": "Quotas",
"links": [],
"namespace": "https://docs.openstack.org/ext/quotas-sets/api/v1.1",
"alias": "os-quota-sets",
"description": "Quotas management support"
}, {
"updated": "2011-08-24T00:00:00+00:00",
"name": "VolumeTypes",
"links": [],
"namespace": "https://docs.openstack.org/ext/volume_types/api/v1.1",
"alias": "os-volume-types",
"description": "Volume types support"
}, {
"updated": "2011-06-23T00:00:00+00:00",
"name": "FlavorExtraSpecs",
"links": [],
"namespace": "https://docs.openstack.org/ext/flavor_extra_specs/api/v1.1",
"alias": "os-flavor-extra-specs",
"description": "Instance type (flavor) extra specs"
}, {
"updated": "2011-09-14T00:00:00+00:00",
"name": "FlavorExtraData",
"links": [],
"namespace": "https://docs.openstack.org/ext/flavor_extra_data/api/v1.1",
"alias": "os-flavor-extra-data",
"description": "Provide additional data for flavors"
}, {
"updated": "2011-08-17T00:00:00+00:00",
"name": "VirtualInterfaces",
"links": [],
"namespace": "https://docs.openstack.org/ext/virtual_interfaces/api/v1.1",
"alias": "virtual_interfaces",
"description": "Virtual interface support"
}, {
"updated": "2011-07-19T00:00:00+00:00",
"name": "Createserverext",
"links": [],
"namespace": "https://docs.openstack.org/ext/createserverext/api/v1.1",
"alias": "os-create-server-ext",
"description": "Extended support to the Create Server v1.1 API"
}, {
"updated": "2011-08-08T00:00:00+00:00",
"name": "Keypairs",
"links": [],
"namespace": "https://docs.openstack.org/ext/keypairs/api/v1.1",
"alias": "os-keypairs",
"description": "Keypair Support"
}, {
"updated": "2011-08-25T00:00:00+00:00",
"name": "VSAs",
"links": [],
"namespace": "https://docs.openstack.org/ext/vsa/api/v1.1",
"alias": "zadr-vsa",
"description": "Virtual Storage Arrays support"
}, {
"updated": "2011-08-19T00:00:00+00:00",
"name": "SimpleTenantUsage",
"links": [],
"namespace": "https://docs.openstack.org/ext/os-simple-tenant-usage/api/v1.1",
"alias": "os-simple-tenant-usage",
"description": "Simple tenant usage extension"
}, {
"updated": "2011-08-18T00:00:00+00:00",
"name": "Rescue",
"links": [],
"namespace": "https://docs.openstack.org/ext/rescue/api/v1.1",
"alias": "os-rescue",
"description": "Instance rescue mode"
}, {
"updated": "2011-07-21T00:00:00+00:00",
"name": "SecurityGroups",
"links": [],
"namespace": "https://docs.openstack.org/ext/securitygroups/api/v1.1",
"alias": "security_groups",
"description": "Security group support"
}, {
"updated": "2011-06-16T00:00:00+00:00",
"name": "Floating_ips",
"links": [],
"namespace": "https://docs.openstack.org/ext/floating_ips/api/v1.1",
"alias": "os-floating-ips",
"description": "Floating IPs support"
}]
}

View File

@ -0,0 +1,83 @@
{
"flavors": [{
"rxtx_quota": 0,
"name": "m1.medium",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/flavors/3",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/flavors/3",
"rel": "bookmark"
}],
"ram": 4096,
"vcpus": 2,
"rxtx_cap": 0,
"swap": 0,
"disk": 40,
"id": 3
}, {
"rxtx_quota": 0,
"name": "m1.large",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/flavors/4",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/flavors/4",
"rel": "bookmark"
}],
"ram": 8192,
"vcpus": 4,
"rxtx_cap": 0,
"swap": 0,
"disk": 80,
"id": 4
}, {
"rxtx_quota": 0,
"name": "m1.tiny",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/flavors/1",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/flavors/1",
"rel": "bookmark"
}],
"ram": 512,
"vcpus": 1,
"rxtx_cap": 0,
"swap": 0,
"disk": 0,
"id": 1
}, {
"rxtx_quota": 0,
"name": "m1.xlarge",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/flavors/5",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/flavors/5",
"rel": "bookmark"
}],
"ram": 16384,
"vcpus": 8,
"rxtx_cap": 0,
"swap": 0,
"disk": 160,
"id": 5
}, {
"rxtx_quota": 0,
"name": "m1.small",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/flavors/2",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/flavors/2",
"rel": "bookmark"
}],
"ram": 2048,
"vcpus": 1,
"rxtx_cap": 0,
"swap": 0,
"disk": 20,
"id": 2
}]
}

View File

@ -0,0 +1,81 @@
{
"images": [{
"status": "ACTIVE",
"updated": "2012-02-02T19:11:00Z",
"name": "oneiric-server-cloudimg-amd64",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/images/15",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/images/15",
"rel": "bookmark"
}],
"created": "2012-02-02T19:10:52Z",
"progress": 100,
"id": "15",
"metadata": {
"kernel_id": "14",
"min_disk": 0,
"min_ram": 0,
"owner": "1"
}
}, {
"status": "ACTIVE",
"updated": "2012-02-02T19:10:51Z",
"name": "oneiric-server-cloudimg-amd64-kernel",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/images/14",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/images/14",
"rel": "bookmark"
}],
"created": "2012-02-02T19:10:50Z",
"progress": 100,
"id": "14",
"metadata": {
"min_disk": 0,
"owner": "1",
"min_ram": 0
}
}, {
"status": "ACTIVE",
"updated": "2012-02-02T19:10:41Z",
"name": "natty-server-cloudimg-amd64",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/images/13",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/images/13",
"rel": "bookmark"
}],
"created": "2012-02-02T19:10:33Z",
"progress": 100,
"id": "13",
"metadata": {
"kernel_id": "12",
"min_disk": 0,
"min_ram": 0,
"owner": "1"
}
}, {
"status": "ACTIVE",
"updated": "2012-02-02T19:10:33Z",
"name": "natty-server-cloudimg-amd64-kernel",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/images/12",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/images/12",
"rel": "bookmark"
}],
"created": "2012-02-02T19:10:32Z",
"progress": 100,
"id": "12",
"metadata": {
"min_disk": 0,
"owner": "1",
"min_ram": 0
}
}]
}

View File

@ -0,0 +1,46 @@
{
"server": {
"status": "ACTIVE",
"updated": "2012-03-23T01:30:26Z",
"hostId": "881706597197955ac7cc4b353bc7ec884e13fa280de9cc82057796cb",
"user_id": "508151008",
"name": "mygroup-72c",
"links": [{
"href": "https://nova-api.trystack.org:9774/v1.1/37/servers/1459",
"rel": "self"
}, {
"href": "https://nova-api.trystack.org:9774/37/servers/1459",
"rel": "bookmark"
}],
"addresses": {
"internet": [{
"version": 4,
"addr": "8.21.28.47"
}]
},
"tenant_id": "37",
"image": {
"id": "14",
"links": [{
"href": "https://nova-api.trystack.org:9774/37/images/14",
"rel": "bookmark"
}]
},
"created": "2012-03-23T01:30:26Z",
"uuid": "2443c9c7-9791-412e-ac09-a6d55ec25335",
"accessIPv4": "",
"accessIPv6": "",
"key_name": null,
"progress": 100,
"flavor": {
"id": "1",
"links": [{
"href": "https://nova-api.trystack.org:9774/37/flavors/1",
"rel": "bookmark"
}]
},
"config_drive": "",
"id": 1459,
"metadata": {}
}
}