mirror of https://github.com/apache/jclouds.git
Issue 27: portability of error handling in eucalyptus where errors are text/plain on 400; changed euc m1.small to accept 64bit
This commit is contained in:
parent
15c878c1bf
commit
0d7d2fe778
|
@ -21,6 +21,7 @@ package org.jclouds.aws.ec2.compute.domain;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Predicates.not;
|
||||
import static org.jclouds.compute.predicates.ImagePredicates.any;
|
||||
import static org.jclouds.compute.predicates.ImagePredicates.idIn;
|
||||
import static org.jclouds.compute.predicates.ImagePredicates.is64Bit;
|
||||
|
||||
|
@ -75,23 +76,24 @@ public class EC2Hardware extends HardwareImpl {
|
|||
|
||||
EC2Hardware(String instanceType, Iterable<? extends Processor> processors, Integer ram,
|
||||
Iterable<? extends Volume> volumes, RootDeviceType rootDeviceType) {
|
||||
super(instanceType, instanceType, instanceType, null, null, ImmutableMap.<String, String> of(), processors, ram,
|
||||
volumes, hasRootDeviceType(rootDeviceType));
|
||||
this(null, instanceType, processors, ram, volumes, hasRootDeviceType(rootDeviceType));
|
||||
}
|
||||
|
||||
EC2Hardware(Location location, String instanceType, Iterable<? extends Processor> processors, Integer ram,
|
||||
Iterable<? extends Volume> volumes, Predicate<Image> supportsImage) {
|
||||
super(instanceType, instanceType, instanceType, location, null, ImmutableMap.<String, String> of(), processors,
|
||||
ram, volumes, supportsImage);
|
||||
this.instanceType = instanceType;
|
||||
}
|
||||
|
||||
EC2Hardware(String instanceType, Iterable<? extends Processor> processors, Integer ram,
|
||||
Iterable<? extends Volume> volumes, boolean is64Bit) {
|
||||
super(instanceType, instanceType, instanceType, null, null, ImmutableMap.<String, String> of(), processors, ram,
|
||||
volumes, is64Bit ? is64Bit() : not(is64Bit()));
|
||||
this.instanceType = instanceType;
|
||||
this(null, instanceType, processors, ram, volumes, is64Bit ? is64Bit() : not(is64Bit()));
|
||||
}
|
||||
|
||||
public EC2Hardware(Location location, String instanceType, Iterable<? extends Processor> processors, Integer ram,
|
||||
Iterable<? extends Volume> volumes, String[] ids) {
|
||||
super(instanceType, instanceType, instanceType, location, null, ImmutableMap.<String, String> of(), processors,
|
||||
ram, volumes, (ids.length == 0 ? is64Bit() : idIn(Arrays.asList(ids))));
|
||||
this.instanceType = instanceType;
|
||||
this(location, instanceType, processors, ram, volumes, (ids.length == 0 ? is64Bit() : idIn(Arrays.asList(ids))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,6 +109,14 @@ public class EC2Hardware extends HardwareImpl {
|
|||
public static final EC2Hardware M1_SMALL = new EC2Hardware(InstanceType.M1_SMALL, ImmutableList.of(new Processor(
|
||||
1.0, 1.0)), 1740, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(150.0f,
|
||||
"/dev/sda2", false, false)), false);
|
||||
/**
|
||||
* In Eucalyptus, m1.small can run 64bit images.
|
||||
*
|
||||
* @see InstanceType#M1_SMALL
|
||||
*/
|
||||
public static final EC2Hardware M1_SMALL_EUCALYPTUS = new EC2Hardware(null, InstanceType.M1_SMALL, ImmutableList
|
||||
.of(new Processor(1.0, 1.0)), 1740, ImmutableList.of(new VolumeImpl(10.0f, "/dev/sda1", true, false),
|
||||
new VolumeImpl(150.0f, "/dev/sda2", false, false)), any());
|
||||
|
||||
/**
|
||||
* @see InstanceType#T1_MICRO
|
||||
|
|
|
@ -26,7 +26,6 @@ import javax.inject.Inject;
|
|||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.AWSResponseException;
|
||||
import org.jclouds.aws.ec2.EC2Client;
|
||||
import org.jclouds.aws.ec2.compute.domain.RegionNameAndIngressRules;
|
||||
import org.jclouds.aws.ec2.domain.IpProtocol;
|
||||
|
@ -72,13 +71,8 @@ public class CreateSecurityGroupIfNeeded implements Function<RegionNameAndIngres
|
|||
if (ports.length > 0) {
|
||||
authorizeGroupToItself(region, name);
|
||||
}
|
||||
} catch (AWSResponseException e) {
|
||||
if (e.getError().getCode().equals("InvalidGroup.Duplicate")
|
||||
|| e.getError().getMessage().endsWith("already exists")) {
|
||||
logger.debug("<< reused securityGroup(%s)", name);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
} catch (IllegalStateException e) {
|
||||
logger.debug("<< reused securityGroup(%s)", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
|
|||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.domain.LocationScope;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.annotations.Provider;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -56,11 +57,14 @@ public class EC2HardwareSupplier implements Supplier<Set<? extends Hardware>> {
|
|||
protected Logger logger = Logger.NULL;
|
||||
private final Supplier<Set<? extends Location>> locations;
|
||||
private final String[] ccAmis;
|
||||
private final String providerName;
|
||||
|
||||
@Inject
|
||||
EC2HardwareSupplier(Supplier<Set<? extends Location>> locations, @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis) {
|
||||
EC2HardwareSupplier(Supplier<Set<? extends Location>> locations, @Provider String providerName,
|
||||
@Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis) {
|
||||
this.locations = locations;
|
||||
this.ccAmis = ccAmis;
|
||||
this.providerName=providerName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -82,8 +86,9 @@ public class EC2HardwareSupplier implements Supplier<Set<? extends Hardware>> {
|
|||
new VolumeImpl(840.0f, "/dev/sdc", false, false)), ccAmis));
|
||||
}
|
||||
sizes.addAll(ImmutableSet.<Hardware> of(EC2Hardware.T1_MICRO, EC2Hardware.C1_MEDIUM, EC2Hardware.C1_XLARGE,
|
||||
EC2Hardware.M1_LARGE, EC2Hardware.M1_SMALL, EC2Hardware.M1_XLARGE, EC2Hardware.M2_XLARGE,
|
||||
EC2Hardware.M2_2XLARGE, EC2Hardware.M2_4XLARGE));
|
||||
EC2Hardware.M1_LARGE, "eucalyptus".equals(providerName) ? EC2Hardware.M1_SMALL_EUCALYPTUS
|
||||
: EC2Hardware.M1_SMALL, EC2Hardware.M1_XLARGE, EC2Hardware.M2_XLARGE, EC2Hardware.M2_2XLARGE,
|
||||
EC2Hardware.M2_4XLARGE));
|
||||
return sizes;
|
||||
}
|
||||
}
|
|
@ -21,6 +21,8 @@ package org.jclouds.aws.handlers;
|
|||
|
||||
import static org.jclouds.http.HttpUtils.releasePayload;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -38,6 +40,7 @@ import org.jclouds.http.HttpResponseException;
|
|||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
import org.jclouds.util.Utils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
|
@ -65,33 +68,49 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
|
|||
HttpRequest request = command.getRequest();
|
||||
Exception exception = new HttpResponseException(command, response);
|
||||
try {
|
||||
AWSError error = utils.parseAWSErrorFromContent(request, response);
|
||||
exception = error != null ? new AWSResponseException(command, response, error) : exception;
|
||||
String notFoundMessage = error != null ? error.getMessage() : String.format("%s -> %s", request
|
||||
.getRequestLine(), response.getStatusLine());
|
||||
AWSError error = null;
|
||||
String message = null;
|
||||
if (response.getPayload().getContentType() != null
|
||||
&& response.getPayload().getContentType().indexOf("xml") != -1) {
|
||||
error = utils.parseAWSErrorFromContent(request, response);
|
||||
if (error != null) {
|
||||
message = error.getMessage();
|
||||
exception = new AWSResponseException(command, response, error);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
message = Utils.toStringAndClose(response.getPayload().getInput());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
message = message != null ? message : String.format("%s -> %s", request.getRequestLine(), response
|
||||
.getStatusLine());
|
||||
switch (response.getStatusCode()) {
|
||||
case 400:
|
||||
if (error != null && error.getCode().endsWith(".NotFound") || error.getCode().endsWith(".Unknown"))
|
||||
exception = new ResourceNotFoundException(notFoundMessage, exception);
|
||||
else if (error != null && error.getCode().equals("IncorrectState"))
|
||||
exception = new IllegalStateException(error.getMessage(), exception);
|
||||
else if (error != null && error.getCode().equals("AuthFailure"))
|
||||
exception = new AuthorizationException(command.getRequest(), error != null ? error.getMessage()
|
||||
: response.getStatusLine());
|
||||
if (error != null && error.getCode() != null
|
||||
&& (error.getCode().endsWith(".NotFound") || error.getCode().endsWith(".Unknown")))
|
||||
exception = new ResourceNotFoundException(message, exception);
|
||||
else if ((error != null && error.getCode() != null && (error.getCode().equals("IncorrectState") || error
|
||||
.getCode().equals("InvalidGroup.Duplicate")))
|
||||
|| (message != null && message.indexOf("already exists") != -1))
|
||||
exception = new IllegalStateException(message, exception);
|
||||
else if (error != null && error.getCode() != null && error.getCode().equals("AuthFailure"))
|
||||
exception = new AuthorizationException(command.getRequest(), message);
|
||||
else if (message != null && message.indexOf("Failed to bind the following fields") != -1)// Eucalyptus
|
||||
exception = new IllegalArgumentException(message, exception);
|
||||
break;
|
||||
case 401:
|
||||
case 403:
|
||||
exception = new AuthorizationException(command.getRequest(), error != null ? error.getMessage()
|
||||
: response.getStatusLine());
|
||||
exception = new AuthorizationException(command.getRequest(), message);
|
||||
break;
|
||||
case 404:
|
||||
if (!command.getRequest().getMethod().equals("DELETE")) {
|
||||
String container = request.getEndpoint().getHost();
|
||||
String key = request.getEndpoint().getPath();
|
||||
if (key == null || key.equals("/"))
|
||||
exception = new ContainerNotFoundException(container, notFoundMessage);
|
||||
exception = new ContainerNotFoundException(container, message);
|
||||
else
|
||||
exception = new KeyNotFoundException(container, key, notFoundMessage);
|
||||
exception = new KeyNotFoundException(container, key, message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -303,12 +303,24 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
|||
private void cleanupExtendedStuff(SecurityGroupClient securityGroupClient, KeyPairClient keyPairClient, String tag)
|
||||
throws InterruptedException {
|
||||
try {
|
||||
securityGroupClient.deleteSecurityGroupInRegion(null, tag);
|
||||
for (SecurityGroup group : securityGroupClient.describeSecurityGroupsInRegion(null))
|
||||
if (group.getName().startsWith("jclouds#" + tag) || group.getName().equals(tag)) {
|
||||
System.err.printf("deleting group %s%n", group.getName());
|
||||
securityGroupClient.deleteSecurityGroupInRegion(null, group.getName());
|
||||
} else {
|
||||
System.err.printf("group %s didn't match %s%n", group.getName(), tag);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
try {
|
||||
keyPairClient.deleteKeyPairInRegion(null, tag);
|
||||
for (KeyPair pair : keyPairClient.describeKeyPairsInRegion(null))
|
||||
if (pair.getKeyName().startsWith("jclouds#" + tag) || pair.getKeyName().equals(tag)) {
|
||||
System.err.printf("deleting key %s%n", pair.getKeyName());
|
||||
keyPairClient.deleteKeyPairInRegion(null, pair.getKeyName());
|
||||
} else {
|
||||
System.err.printf("key %s didn't match %s%n", pair.getKeyName(), tag);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
|
|
@ -46,8 +46,7 @@ public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest
|
|||
Template defaultTemplate = client.templateBuilder().build();
|
||||
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
|
||||
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.CENTOS);
|
||||
// 64 bit implied 4 ecus
|
||||
assertEquals(getCores(template.getHardware()), 4.0d);
|
||||
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -69,6 +69,30 @@ public class ParseAWSErrorFromXmlContentTest {
|
|||
"<Error><Code>IncorrectState</Code></Error>", IllegalStateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test400WithInvalidGroupDuplicateIllegalStateException() {
|
||||
assertCodeMakes("GET", URI.create("https://amazonaws.com/foo"), 400, "",
|
||||
"<Error><Code>InvalidGroup.Duplicate</Code></Error>", IllegalStateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test400WithTextPlainIllegalArgumentException() {
|
||||
assertCodeMakes("GET", URI.create("https://amazonaws.com/foo"), 400, "Bad Request", "text/plain",
|
||||
"Failure: 400 Bad Request\nFailed to bind the following fields\nMonitoring.Enabled = true\n\n\n",
|
||||
IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test400WithGroupAlreadyExistsEucalyptusIllegalStateException() {
|
||||
assertCodeMakes(
|
||||
"GET",
|
||||
URI.create("https://amazonaws.com/foo"),
|
||||
400,
|
||||
"",
|
||||
"<?xml version=\"1.0\"?><Response><Errors><Error><Code>Groups</Code><Message>\nError adding network group: group named jclouds#eucrun#Eucalyptus already exists\nError adding network group: group named jclouds#eucrun#Eucalyptus already exists</Message></Error></Errors><RequestID>e0133975-3bc5-456d-9753-1d61b27e07e9</RequestID></Response>",
|
||||
IllegalStateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test400WithAuthFailureSetsAuthorizationException() {
|
||||
assertCodeMakes("GET", URI.create("https://amazonaws.com/foo"), 400, "",
|
||||
|
@ -77,6 +101,11 @@ public class ParseAWSErrorFromXmlContentTest {
|
|||
|
||||
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
|
||||
Class<? extends Exception> expected) {
|
||||
assertCodeMakes(method, uri, statusCode, message, "text/xml", content, expected);
|
||||
}
|
||||
|
||||
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
|
||||
String content, Class<? extends Exception> expected) {
|
||||
|
||||
ParseAWSErrorFromXmlContent function = Guice.createInjector(new SaxParserModule(), new AbstractModule() {
|
||||
|
||||
|
@ -92,8 +121,7 @@ public class ParseAWSErrorFromXmlContentTest {
|
|||
HttpRequest request = new HttpRequest(method, uri);
|
||||
HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Utils
|
||||
.toInputStream(content)));
|
||||
response.getPayload().setContentType("text/xml");
|
||||
//TODO also check application/unknown
|
||||
response.getPayload().setContentType(contentType);
|
||||
|
||||
expect(command.getRequest()).andReturn(request).atLeastOnce();
|
||||
command.setException(classEq(expected));
|
||||
|
|
|
@ -33,23 +33,30 @@ public class ErrorHandlerTest extends BaseHandlerTest {
|
|||
public static final String errorFromAmazonIfYouDontRemoveTransferEncodingHeader = "<Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>7C59925D75D15561</RequestId><HostId>fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb</HostId></Error>";
|
||||
|
||||
ParseSax<AWSError> createParser() {
|
||||
ParseSax<AWSError> parser = (ParseSax<AWSError>) factory.create(injector
|
||||
.getInstance(ErrorHandler.class));
|
||||
ParseSax<AWSError> parser = (ParseSax<AWSError>) factory.create(injector.getInstance(ErrorHandler.class));
|
||||
return parser;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorFromAmazonIfYouDontRemoveTransferEncodingHeader() throws HttpException {
|
||||
ParseSax<AWSError> parser = createParser();
|
||||
AWSError error = parser.parse(Utils
|
||||
.toInputStream(errorFromAmazonIfYouDontRemoveTransferEncodingHeader));
|
||||
AWSError error = parser.parse(Utils.toInputStream(errorFromAmazonIfYouDontRemoveTransferEncodingHeader));
|
||||
assertEquals(error.getCode(), "NotImplemented");
|
||||
assertEquals(error.getMessage(),
|
||||
"A header you provided implies functionality that is not implemented");
|
||||
assertEquals(error.getMessage(), "A header you provided implies functionality that is not implemented");
|
||||
assertEquals(error.getDetails().get("Header"), "Transfer-Encoding");
|
||||
assertEquals(error.getRequestId(), "7C59925D75D15561");
|
||||
assertEquals(error.getDetails().get("HostId"),
|
||||
"fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb");
|
||||
assertEquals(error.getDetails().get("HostId"), "fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorFromEucalyptusWhenGroupAlreadyExists() throws HttpException {
|
||||
ParseSax<AWSError> parser = createParser();
|
||||
AWSError error = parser
|
||||
.parse(Utils
|
||||
.toInputStream("<?xml version=\"1.0\"?><Response><Errors><Error><Code>Groups</Code><Message>\nError adding network group: group named jclouds#eucrun#Eucalyptus already exists\nError adding network group: group named jclouds#eucrun#Eucalyptus already exists</Message></Error></Errors><RequestID>e0133975-3bc5-456d-9753-1d61b27e07e9</RequestID></Response>"));
|
||||
assertEquals(error.getCode(), "Groups");
|
||||
assertEquals(
|
||||
error.getMessage(),
|
||||
"Error adding network group: group named jclouds#eucrun#Eucalyptus already exists\nError adding network group: group named jclouds#eucrun#Eucalyptus already exists");
|
||||
}
|
||||
|
||||
public static final String badRequestWhenSourceIsDestBucketOnCopy400 = "<Error><Code>InvalidRequest</Code><Message>The Source and Destination may not be the same when the MetadataDirective is Copy.</Message><RequestId>54C77CAF4D42474B</RequestId><HostId>SJecknEUUUx88/65VAKbCdKSOCkpuVTeu7ZG9in9x9NTNglGnoxdbALCfS4k/DUZ</HostId></Error>";
|
||||
|
|
|
@ -19,11 +19,13 @@
|
|||
|
||||
package org.jclouds.compute.predicates;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.compute.domain.OperatingSystem;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Container for operating system filters (predicates).
|
||||
|
@ -48,7 +50,7 @@ public class OperatingSystemPredicates {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
for (String toMatch : ImmutableSet.of(os.getName(), os.getDescription()))
|
||||
for (String toMatch : searchStrings(os))
|
||||
if (toMatch != null && toMatch.toLowerCase().indexOf("windows") != -1)
|
||||
return false;
|
||||
return true;
|
||||
|
@ -76,7 +78,7 @@ public class OperatingSystemPredicates {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
for (String toMatch : ImmutableSet.of(os.getName(), os.getDescription()))
|
||||
for (String toMatch : searchStrings(os))
|
||||
if (toMatch != null && toMatch.toLowerCase().indexOf("ubuntu") != -1
|
||||
|| toMatch.toLowerCase().indexOf("debian") != -1)
|
||||
return true;
|
||||
|
@ -107,7 +109,7 @@ public class OperatingSystemPredicates {
|
|||
}
|
||||
}
|
||||
|
||||
for (String toMatch : ImmutableSet.of(os.getName(), os.getDescription()))
|
||||
for (String toMatch : searchStrings(os))
|
||||
if (toMatch.toLowerCase().indexOf("centos") != -1 || toMatch.toLowerCase().indexOf("rhel") != -1
|
||||
|| toMatch.toLowerCase().replace(" ", "").indexOf("redhate") != -1
|
||||
|| toMatch.toLowerCase().indexOf("fedora") != -1)
|
||||
|
@ -136,7 +138,7 @@ public class OperatingSystemPredicates {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
for (String toMatch : ImmutableSet.of(os.getName(), os.getDescription()))
|
||||
for (String toMatch : searchStrings(os))
|
||||
if (toMatch != null && toMatch.toLowerCase().indexOf("suse") != -1)
|
||||
return true;
|
||||
return false;
|
||||
|
@ -173,4 +175,13 @@ public class OperatingSystemPredicates {
|
|||
};
|
||||
}
|
||||
|
||||
static Iterable<String> searchStrings(OperatingSystem os) {
|
||||
Set<String> search = Sets.newLinkedHashSet();
|
||||
if (os.getName() != null)
|
||||
search.add(os.getName());
|
||||
if (os.getDescription() != null)
|
||||
search.add(os.getDescription());
|
||||
return search;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue