diff --git a/awsapi/src/com/cloud/bridge/service/EC2MainServlet.java b/awsapi/src/com/cloud/bridge/service/EC2MainServlet.java index 8361f6ede8a..4cf5f88232d 100644 --- a/awsapi/src/com/cloud/bridge/service/EC2MainServlet.java +++ b/awsapi/src/com/cloud/bridge/service/EC2MainServlet.java @@ -94,7 +94,7 @@ public class EC2MainServlet extends HttpServlet{ if(!isEC2APIEnabled){ //response.sendError(404, "EC2 API is disabled."); response.setStatus(404); - faultResponse(response, "404" , "EC2 API is disabled."); + faultResponse(response, "Unavailable" , "EC2 API is disabled"); return; } diff --git a/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java b/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java index 83645a38de8..40cabb66b68 100644 --- a/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java +++ b/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java @@ -39,7 +39,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Set; import java.util.UUID; import javax.inject.Inject; @@ -92,10 +91,9 @@ import com.amazon.ec2.DescribeVolumesResponse; import com.amazon.ec2.DetachVolumeResponse; import com.amazon.ec2.DisassociateAddressResponse; import com.amazon.ec2.GetPasswordDataResponse; -import com.amazon.ec2.GroupItemType; import com.amazon.ec2.ImportKeyPairResponse; -import com.amazon.ec2.LaunchPermissionItemType; import com.amazon.ec2.ModifyImageAttributeResponse; +import com.amazon.ec2.ModifyInstanceAttributeResponse; import com.amazon.ec2.RebootInstancesResponse; import com.amazon.ec2.RegisterImageResponse; import com.amazon.ec2.ReleaseAddressResponse; @@ -105,9 +103,7 @@ import com.amazon.ec2.RunInstancesResponse; import com.amazon.ec2.StartInstancesResponse; import com.amazon.ec2.StopInstancesResponse; import com.amazon.ec2.TerminateInstancesResponse; -import com.cloud.bridge.model.CloudStackUserVO; import com.cloud.bridge.model.UserCredentialsVO; -import com.cloud.bridge.persist.dao.CloudStackConfigurationDao; import com.cloud.bridge.persist.dao.CloudStackUserDaoImpl; import com.cloud.bridge.persist.dao.OfferingDaoImpl; import com.cloud.bridge.persist.dao.UserCredentialsDaoImpl; @@ -143,6 +139,7 @@ import com.cloud.bridge.service.core.ec2.EC2InstanceFilterSet; import com.cloud.bridge.service.core.ec2.EC2IpPermission; import com.cloud.bridge.service.core.ec2.EC2KeyPairFilterSet; import com.cloud.bridge.service.core.ec2.EC2ModifyImageAttribute; +import com.cloud.bridge.service.core.ec2.EC2ModifyInstanceAttribute; import com.cloud.bridge.service.core.ec2.EC2RebootInstances; import com.cloud.bridge.service.core.ec2.EC2RegisterImage; import com.cloud.bridge.service.core.ec2.EC2ReleaseAddress; @@ -151,8 +148,6 @@ import com.cloud.bridge.service.core.ec2.EC2SecurityGroup; import com.cloud.bridge.service.core.ec2.EC2SnapshotFilterSet; import com.cloud.bridge.service.core.ec2.EC2StartInstances; import com.cloud.bridge.service.core.ec2.EC2StopInstances; -import com.cloud.bridge.service.core.ec2.EC2TagKeyValue; -import com.cloud.bridge.service.core.ec2.EC2TagTypeId; import com.cloud.bridge.service.core.ec2.EC2Tags; import com.cloud.bridge.service.core.ec2.EC2TagsFilterSet; import com.cloud.bridge.service.core.ec2.EC2Volume; @@ -289,6 +284,7 @@ public class EC2RestServlet extends HttpServlet { else if (action.equalsIgnoreCase( "DetachVolume" )) detachVolume(request, response); else if (action.equalsIgnoreCase( "DisassociateAddress" )) disassociateAddress(request, response); else if (action.equalsIgnoreCase( "ModifyImageAttribute" )) modifyImageAttribute(request, response); + else if (action.equalsIgnoreCase( "ModifyInstanceAttribute" )) modifyInstanceAttribute(request, response); else if (action.equalsIgnoreCase( "RebootInstances" )) rebootInstances(request, response); else if (action.equalsIgnoreCase( "RegisterImage" )) registerImage(request, response); else if (action.equalsIgnoreCase( "ReleaseAddress" )) releaseAddress(request, response); @@ -318,8 +314,14 @@ public class EC2RestServlet extends HttpServlet { } catch( EC2ServiceException e ) { response.setStatus(e.getErrorCode()); - if (e.getCause() != null && e.getCause() instanceof AxisFault) - faultResponse(response, ((AxisFault)e.getCause()).getFaultCode().getLocalPart(), e.getMessage()); + if (e.getCause() != null && e.getCause() instanceof AxisFault) { + String errorCode = ((AxisFault)e.getCause()).getFaultCode().getLocalPart(); + if (errorCode.startsWith("Client.")) // only in a SOAP API client error code is prefixed with Client. + errorCode = errorCode.split("Client.")[1]; + else if (errorCode.startsWith("Server.")) // only in a SOAP API server error code is prefixed with Server. + errorCode = errorCode.split("Server.")[1]; + faultResponse(response, errorCode, e.getMessage()); + } else { logger.error("EC2ServiceException: " + e.getMessage(), e); endResponse(response, e.toString()); @@ -395,11 +397,6 @@ public class EC2RestServlet extends HttpServlet { endResponse(response, "SetUserKeys exception " + e.getMessage()); return; } - - // prime UserContext here -// logger.debug("initializing context"); - UserContext context = UserContext.current(); - try { txn = Transaction.open(Transaction.AWSAPI_DB); // -> use the keys to see if the account actually exists @@ -681,17 +678,23 @@ public class EC2RestServlet extends HttpServlet { String[] volumeId = request.getParameterValues( "VolumeId" ); if ( null != volumeId && 0 < volumeId.length ) EC2request.setId( volumeId[0] ); - else { response.sendError(530, "Missing VolumeId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - VolumeId"); + } String[] instanceId = request.getParameterValues( "InstanceId" ); if ( null != instanceId && 0 < instanceId.length ) EC2request.setInstanceId( instanceId[0] ); - else { response.sendError(530, "Missing InstanceId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } String[] device = request.getParameterValues( "Device" ); if ( null != device && 0 < device.length ) EC2request.setDevice( device[0] ); - else { response.sendError(530, "Missing Device parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Device"); + } // -> execute the request AttachVolumeResponse EC2response = EC2SoapServiceImpl.toAttachVolumeResponse( ServiceProvider.getInstance().getEC2Engine().attachVolume( EC2request )); @@ -709,7 +712,9 @@ public class EC2RestServlet extends HttpServlet { String[] groupName = request.getParameterValues( "GroupName" ); if ( null != groupName && 0 < groupName.length ) EC2request.setName( groupName[0] ); - else { response.sendError(530, "Missing GroupName parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - GroupName"); + } // -> not clear how many parameters there are until we fail to get IpPermissions.n.IpProtocol int nCount = 1, mCount; @@ -772,8 +777,7 @@ public class EC2RestServlet extends HttpServlet { } while( true ); if (1 == nCount) { - response.sendError(530, "At least one IpPermissions required" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - IpPermissions"); } // -> execute the request @@ -790,7 +794,9 @@ public class EC2RestServlet extends HttpServlet { String[] groupName = request.getParameterValues( "GroupName" ); if ( null != groupName && 0 < groupName.length ) EC2request.setName( groupName[0] ); - else { response.sendError(530, "Missing GroupName parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter 'Groupname'"); + } // -> not clear how many parameters there are until we fail to get IpPermissions.n.IpProtocol int nCount = 1; @@ -852,8 +858,9 @@ public class EC2RestServlet extends HttpServlet { } while( true ); - if (1 == nCount) { response.sendError(530, "At least one IpPermissions required" ); return; } - + if (1 == nCount) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - IpPermissions"); + } // -> execute the request AuthorizeSecurityGroupIngressResponse EC2response = EC2SoapServiceImpl.toAuthorizeSecurityGroupIngressResponse( @@ -868,7 +875,9 @@ public class EC2RestServlet extends HttpServlet { String[] volumeId = request.getParameterValues( "VolumeId" ); if ( null != volumeId && 0 < volumeId.length ) EC2request.setId(volumeId[0]); - else { response.sendError(530, "Missing VolumeId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter 'VolumeId'"); + } String[] instanceId = request.getParameterValues( "InstanceId" ); if ( null != instanceId && 0 < instanceId.length ) @@ -890,7 +899,9 @@ public class EC2RestServlet extends HttpServlet { String[] volumeId = request.getParameterValues( "VolumeId" ); if ( null != volumeId && 0 < volumeId.length ) EC2request.setId(volumeId[0]); - else { response.sendError(530, "Missing VolumeId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - VolumeId"); + } // -> execute the request DeleteVolumeResponse EC2response = EC2SoapServiceImpl.toDeleteVolumeResponse( ServiceProvider.getInstance().getEC2Engine().deleteVolume( EC2request )); @@ -904,7 +915,9 @@ public class EC2RestServlet extends HttpServlet { String[] zoneName = request.getParameterValues( "AvailabilityZone" ); if ( null != zoneName && 0 < zoneName.length ) EC2request.setZoneName( zoneName[0] ); - else { response.sendError(530, "Missing AvailabilityZone parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing parameter - AvailabilityZone"); + } String[] size = request.getParameterValues( "Size" ); String[] snapshotId = request.getParameterValues("SnapshotId"); @@ -922,9 +935,9 @@ public class EC2RestServlet extends HttpServlet { } else if (useSnapshot && !useSize) { EC2request.setSnapshotId(snapshotId[0]); } else if (useSize && useSnapshot) { - response.sendError(530, "Size and SnapshotId parameters are mutually exclusive" ); return; + throw new EC2ServiceException( ClientError.InvalidParameterCombination, "Parameters 'Size' and 'SnapshotId' are mutually exclusive"); } else { - response.sendError(530, "Size or SnapshotId has to be specified" ); return; + throw new EC2ServiceException( ClientError.MissingParamter, "Parameter 'Size' or 'SnapshotId' has to be specified"); } @@ -941,12 +954,15 @@ public class EC2RestServlet extends HttpServlet { String[] name = request.getParameterValues( "GroupName" ); if ( null != name && 0 < name.length ) groupName = name[0]; - else { response.sendError(530, "Missing GroupName parameter" ); return; } - + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - GroupName"); + } String[] desc = request.getParameterValues( "GroupDescription" ); if ( null != desc && 0 < desc.length ) groupDescription = desc[0]; - else { response.sendError(530, "Missing GroupDescription parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - GroupDescription"); + } // -> execute the request CreateSecurityGroupResponse EC2response = EC2SoapServiceImpl.toCreateSecurityGroupResponse( ServiceProvider.getInstance().getEC2Engine().createSecurityGroup( groupName, groupDescription )); @@ -960,7 +976,9 @@ public class EC2RestServlet extends HttpServlet { String[] name = request.getParameterValues( "GroupName" ); if ( null != name && 0 < name.length ) groupName = name[0]; - else { response.sendError(530, "Missing GroupName parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - GroupName"); + } // -> execute the request DeleteSecurityGroupResponse EC2response = EC2SoapServiceImpl.toDeleteSecurityGroupResponse( ServiceProvider.getInstance().getEC2Engine().deleteSecurityGroup( groupName )); @@ -974,7 +992,9 @@ public class EC2RestServlet extends HttpServlet { String[] snapSet = request.getParameterValues( "SnapshotId" ); if ( null != snapSet && 0 < snapSet.length ) snapshotId = snapSet[0]; - else { response.sendError(530, "Missing SnapshotId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - SnapshotId"); + } // -> execute the request DeleteSnapshotResponse EC2response = EC2SoapServiceImpl.toDeleteSnapshotResponse( ServiceProvider.getInstance().getEC2Engine().deleteSnapshot( snapshotId )); @@ -988,7 +1008,9 @@ public class EC2RestServlet extends HttpServlet { String[] volSet = request.getParameterValues( "VolumeId" ); if ( null != volSet && 0 < volSet.length ) volumeId = volSet[0]; - else { response.sendError(530, "Missing VolumeId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - VolumeId"); + } // -> execute the request EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); @@ -1003,7 +1025,9 @@ public class EC2RestServlet extends HttpServlet { String[] imageId = request.getParameterValues( "ImageId" ); if ( null != imageId && 0 < imageId.length ) image.setId( imageId[0] ); - else { response.sendError(530, "Missing ImageId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); + } // -> execute the request DeregisterImageResponse EC2response = EC2SoapServiceImpl.toDeregisterImageResponse( ServiceProvider.getInstance().getEC2Engine().deregisterImage( image )); @@ -1017,16 +1041,25 @@ public class EC2RestServlet extends HttpServlet { String[] instanceId = request.getParameterValues( "InstanceId" ); if ( null != instanceId && 0 < instanceId.length ) EC2request.setInstanceId( instanceId[0] ); - else { response.sendError(530, "Missing InstanceId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } String[] name = request.getParameterValues( "Name" ); if ( null != name && 0 < name.length ) EC2request.setName( name[0] ); - else { response.sendError(530, "Missing Name parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Name"); + } String[] description = request.getParameterValues( "Description" ); - if ( null != description && 0 < description.length ) + if ( null != description && 0 < description.length ) { + if (description[0].length() > 255) + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Length of the value of parameter Description should be less than 255"); EC2request.setDescription( description[0] ); + } + // -> execute the request CreateImageResponse EC2response = EC2SoapServiceImpl.toCreateImageResponse( ServiceProvider.getInstance().getEC2Engine().createImage( EC2request )); @@ -1040,16 +1073,23 @@ public class EC2RestServlet extends HttpServlet { String[] location = request.getParameterValues( "ImageLocation" ); if ( null != location && 0 < location.length ) EC2request.setLocation( location[0] ); - else { response.sendError(530, "Missing ImageLocation parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing parameter - ImageLocation"); + } String[] cloudRedfined = request.getParameterValues( "Architecture" ); if ( null != cloudRedfined && 0 < cloudRedfined.length ) EC2request.setArchitecture( cloudRedfined[0] ); - else { response.sendError(530, "Missing Architecture parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Architecture"); + } String[] name = request.getParameterValues( "Name" ); if ( null != name && 0 < name.length ) EC2request.setName( name[0] ); + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Name"); + } String[] description = request.getParameterValues( "Description" ); if ( null != description && 0 < description.length ) @@ -1068,9 +1108,8 @@ public class EC2RestServlet extends HttpServlet { if ( imageId != null && imageId.length > 0 ) ec2request.setImageId( imageId[0]); else { - response.sendError(530, "Missing ImageId parameter" ); - return; - } + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); + } String[] description = request.getParameterValues( "Description.Value" ); if ( description != null && description.length > 0 ) { @@ -1082,8 +1121,8 @@ public class EC2RestServlet extends HttpServlet { if (ec2request.getLaunchPermissionSet().length > 0) ec2request.setAttribute(ImageAttribute.launchPermission); else { - response.sendError(530, "Missing Attribute parameter - Description/LaunchPermission should be provided" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, + "Missing required parameter - Description/LaunchPermission should be provided"); } } @@ -1135,8 +1174,7 @@ public class EC2RestServlet extends HttpServlet { if ( imageId != null && imageId.length > 0) ec2request.setImageId(imageId[0]); else { - response.sendError(530, "Missing ImageId parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); } String[] attribute = request.getParameterValues( "Attribute" ); @@ -1144,12 +1182,11 @@ public class EC2RestServlet extends HttpServlet { if (attribute[0].equalsIgnoreCase("launchPermission")) ec2request.setAttribute(ImageAttribute.launchPermission); else { - response.sendError(501, "Unsupported Attribute - only launchPermission supported" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, + "Missing required parameter - Description/LaunchPermission should be provided"); } } else { - response.sendError(530, "Missing Attribute parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Attribute"); } EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission(); @@ -1170,12 +1207,13 @@ public class EC2RestServlet extends HttpServlet { String[] imageId = request.getParameterValues( "ImageId" ); if ( null != imageId && 0 < imageId.length ) EC2request.setTemplateId( imageId[0] ); - else { response.sendError(530, "Missing ImageId parameter" ); return; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); + } String[] minCount = request.getParameterValues( "MinCount" ); if ( minCount == null || minCount.length < 1) { - response.sendError(530, "Missing MinCount parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - MinCount"); } else if ( Integer.parseInt(minCount[0]) < 1) { throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MinCount should be greater than 0"); @@ -1185,8 +1223,7 @@ public class EC2RestServlet extends HttpServlet { String[] maxCount = request.getParameterValues( "MaxCount" ); if ( maxCount == null || maxCount.length < 1) { - response.sendError(530, "Missing MaxCount parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - MaxCount"); } else if ( Integer.parseInt(maxCount[0]) < 1) { throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MaxCount should be greater than 0"); @@ -1250,7 +1287,9 @@ public class EC2RestServlet extends HttpServlet { } } } - if (0 == count) { response.sendError(530, "Missing InstanceId parameter" ); return; } + if (0 == count) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } // -> execute the request RebootInstancesResponse EC2response = EC2SoapServiceImpl.toRebootInstancesResponse( ServiceProvider.getInstance().getEC2Engine().rebootInstances(EC2request)); @@ -1274,7 +1313,9 @@ public class EC2RestServlet extends HttpServlet { } } } - if (0 == count) { response.sendError(530, "Missing InstanceId parameter" ); return; } + if (0 == count) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } // -> execute the request StartInstancesResponse EC2response = EC2SoapServiceImpl.toStartInstancesResponse( ServiceProvider.getInstance().getEC2Engine().startInstances(EC2request)); @@ -1298,7 +1339,9 @@ public class EC2RestServlet extends HttpServlet { } } } - if (0 == count) { response.sendError(530, "Missing InstanceId parameter" ); return; } + if (0 == count) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } String[] force = request.getParameterValues("Force"); if ( force != null) { @@ -1327,7 +1370,9 @@ public class EC2RestServlet extends HttpServlet { } } } - if (0 == count) { response.sendError(530, "Missing InstanceId parameter" ); return; } + if (0 == count) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } // -> execute the request EC2request.setDestroyInstances( true ); @@ -1364,7 +1409,8 @@ public class EC2RestServlet extends HttpServlet { } // -> execute the request - DescribeAvailabilityZonesResponse EC2response = EC2SoapServiceImpl.toDescribeAvailabilityZonesResponse( ServiceProvider.getInstance().getEC2Engine().handleRequest( EC2request )); + DescribeAvailabilityZonesResponse EC2response = EC2SoapServiceImpl.toDescribeAvailabilityZonesResponse( + ServiceProvider.getInstance().getEC2Engine().describeAvailabilityZones( EC2request )); serializeResponse(response, EC2response); } @@ -1404,8 +1450,7 @@ public class EC2RestServlet extends HttpServlet { if (imageId != null && imageId.length > 0) ec2request.setImageId(imageId[0]); else { - response.sendError(530, "Missing ImageId parameter"); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ImageId"); } String[] attribute = request.getParameterValues( "Attribute" ); @@ -1415,12 +1460,11 @@ public class EC2RestServlet extends HttpServlet { else if (attribute[0].equalsIgnoreCase("launchPermission")) ec2request.setAttribute(ImageAttribute.launchPermission); else { - response.sendError(501, "Unsupported Attribute - description and launchPermission supported" ); - return; + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Only values supported for paramter Attribute are - Description/LaunchPermission"); } } else { - response.sendError(530, "Missing Attribute parameter"); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Attribute"); } DescribeImageAttributeResponse EC2response = EC2SoapServiceImpl.toDescribeImageAttributeResponse( ServiceProvider.getInstance().getEC2Engine().describeImageAttribute( ec2request )); @@ -1501,9 +1545,8 @@ public class EC2RestServlet extends HttpServlet { EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); String publicIp = request.getParameter( "PublicIp" ); - if (publicIp == null) { - response.sendError(530, "Missing PublicIp parameter"); - return; + if (publicIp == null) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - PublicIp"); } EC2ReleaseAddress ec2Request = new EC2ReleaseAddress(); @@ -1522,13 +1565,11 @@ public class EC2RestServlet extends HttpServlet { String publicIp = request.getParameter( "PublicIp" ); if (null == publicIp) { - response.sendError(530, "Missing PublicIp parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - PublicIp"); } String instanceId = request.getParameter( "InstanceId" ); if (null == instanceId) { - response.sendError(530, "Missing InstanceId parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); } EC2AssociateAddress ec2Request = new EC2AssociateAddress(); @@ -1548,8 +1589,7 @@ public class EC2RestServlet extends HttpServlet { String publicIp = request.getParameter( "PublicIp" ); if (null == publicIp) { - response.sendError(530, "Missing PublicIp parameter" ); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - PublicIp"); } EC2DisassociateAddress ec2Request = new EC2DisassociateAddress(); @@ -1597,27 +1637,20 @@ public class EC2RestServlet extends HttpServlet { private void describeInstanceAttribute( HttpServletRequest request, HttpServletResponse response ) throws ADBException, XMLStreamException, IOException { EC2DescribeInstances EC2request = new EC2DescribeInstances(); - String instanceType = null; + String[] instanceId = request.getParameterValues( "InstanceId" ); + if ( instanceId != null && instanceId.length > 0) + EC2request.addInstanceId( instanceId[0] ); + else + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); - // -> we are only handling queries about the "Attribute=instanceType" - Enumeration names = request.getParameterNames(); - while( names.hasMoreElements()) { - String key = (String)names.nextElement(); - if (key.startsWith("Attribute")) { - String[] value = request.getParameterValues( key ); - if (null != value && 0 < value.length && value[0].equalsIgnoreCase( "instanceType" )) { - instanceType = value[0]; - break; - } + String[] attribute = request.getParameterValues( "Attribute" ); + if (attribute != null && attribute.length > 0) { + if ( !attribute[0].equalsIgnoreCase("instanceType") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Only value supported for paramter Attribute is 'instanceType'"); } - } - if ( null != instanceType ) { - String[] value = request.getParameterValues( "InstanceId" ); - EC2request.addInstanceId( value[0] ); - } - else { - response.sendError(501, "Unsupported - only instanceType supported" ); - return; + } else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Attribute"); } // -> execute the request @@ -1625,6 +1658,38 @@ public class EC2RestServlet extends HttpServlet { serializeResponse(response, EC2response); } + private void modifyInstanceAttribute(HttpServletRequest request, HttpServletResponse response) + throws ADBException, XMLStreamException, IOException { + EC2ModifyInstanceAttribute ec2Request = new EC2ModifyInstanceAttribute(); + + String[] instanceId = request.getParameterValues( "InstanceId" ); + if ( instanceId != null && instanceId.length > 0 ) + ec2Request.setInstanceId(instanceId[0]); + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); + } + + String[] instanceType = request.getParameterValues( "InstanceType.Value" ); + String[] userData = request.getParameterValues( "UserData.Value" ); + + if ( instanceType != null && userData != null ) { + throw new EC2ServiceException( ClientError.InvalidParameterCombination, "Only one attribute can be" + + " specified at a time"); + } + if ( instanceType != null && instanceType.length > 0 ) { + ec2Request.setInstanceType(instanceType[0]); + } else if ( userData != null && userData.length > 0 ) { + ec2Request.setUserData(userData[0]); + } else { + throw new EC2ServiceException( ClientError.MissingParamter, + "Missing parameter - InstanceType/UserData should be provided"); + } + + // -> execute the request + ModifyInstanceAttributeResponse EC2response = EC2SoapServiceImpl.toModifyInstanceAttributeResponse( + ServiceProvider.getInstance().getEC2Engine().modifyInstanceAttribute( ec2Request )); + serializeResponse(response, EC2response); + } private void describeSnapshots( HttpServletRequest request, HttpServletResponse response ) throws ADBException, XMLStreamException, IOException @@ -1653,7 +1718,8 @@ public class EC2RestServlet extends HttpServlet { // -> execute the request EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); - DescribeSnapshotsResponse EC2response = EC2SoapServiceImpl.toDescribeSnapshotsResponse( engine.handleRequest( EC2request )); + DescribeSnapshotsResponse EC2response = EC2SoapServiceImpl.toDescribeSnapshotsResponse( + engine.describeSnapshots( EC2request )); serializeResponse(response, EC2response); } @@ -1685,7 +1751,9 @@ public class EC2RestServlet extends HttpServlet { } // -> execute the request - DescribeVolumesResponse EC2response = EC2SoapServiceImpl.toDescribeVolumesResponse( ServiceProvider.getInstance().getEC2Engine().handleRequest( EC2request )); + EC2Engine engine = ServiceProvider.getInstance().getEC2Engine(); + DescribeVolumesResponse EC2response = EC2SoapServiceImpl.toDescribeVolumesResponse( + ServiceProvider.getInstance().getEC2Engine().describeVolumes( EC2request ), engine); serializeResponse(response, EC2response); } @@ -1779,10 +1847,13 @@ public class EC2RestServlet extends HttpServlet { throws ADBException, XMLStreamException, IOException { String keyName = request.getParameter("KeyName"); + if ( keyName == null ) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - KeyName"); + } + String publicKeyMaterial = request.getParameter("PublicKeyMaterial"); - if (keyName==null && publicKeyMaterial==null) { - response.sendError(530, "Missing parameter"); - return; + if ( publicKeyMaterial == null ) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - PublicKeyMaterial"); } if (!publicKeyMaterial.contains(" ")) @@ -1804,9 +1875,8 @@ public class EC2RestServlet extends HttpServlet { private void createKeyPair(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException { String keyName = request.getParameter("KeyName"); - if (keyName==null) { - response.sendError(530, "Missing KeyName parameter"); - return; + if (keyName==null) { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - KeyName"); } EC2CreateKeyPair ec2Request = new EC2CreateKeyPair(); @@ -1823,8 +1893,7 @@ public class EC2RestServlet extends HttpServlet { throws ADBException, XMLStreamException, IOException { String keyName = request.getParameter("KeyName"); if (keyName==null) { - response.sendError(530, "Missing KeyName parameter"); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - KeyName"); } EC2DeleteKeyPair ec2Request = new EC2DeleteKeyPair(); @@ -1839,8 +1908,7 @@ public class EC2RestServlet extends HttpServlet { throws ADBException, XMLStreamException, IOException { String instanceId = request.getParameter("InstanceId"); if (instanceId==null) { - response.sendError(530, "Missing InstanceId parameter"); - return; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - InstanceId"); } GetPasswordDataResponse EC2Response = EC2SoapServiceImpl.toGetPasswordData( @@ -1881,8 +1949,7 @@ public class EC2RestServlet extends HttpServlet { nCount++; } while (true); if ( resourceIdList.isEmpty() ) { - response.sendError(530, "At least one Resource is required" ); - return null; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ResourceId"); } ec2Request = EC2SoapServiceImpl.toResourceTypeAndIds(ec2Request, resourceIdList); @@ -1899,8 +1966,7 @@ public class EC2RestServlet extends HttpServlet { nCount++; } while (true); if ( resourceTagList.isEmpty() ) { - response.sendError(530, "At least one Tag is required" ); - return null; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - ResourceTag"); } ec2Request = EC2SoapServiceImpl.toResourceTag(ec2Request, resourceTagList); @@ -1944,69 +2010,76 @@ public class EC2RestServlet extends HttpServlet { String[] awsAccess = request.getParameterValues( "AWSAccessKeyId" ); if ( null != awsAccess && 0 < awsAccess.length ) cloudAccessKey = awsAccess[0]; - else { response.sendError(530, "Missing AWSAccessKeyId parameter" ); return false; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - AWSAccessKeyId"); + } String[] clientSig = request.getParameterValues( "Signature" ); if ( null != clientSig && 0 < clientSig.length ) signature = clientSig[0]; - else { response.sendError(530, "Missing Signature parameter" ); return false; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Signature"); + } String[] method = request.getParameterValues( "SignatureMethod" ); if ( null != method && 0 < method.length ) { sigMethod = method[0]; if (!sigMethod.equals( "HmacSHA256" ) && !sigMethod.equals( "HmacSHA1" )) { - response.sendError(531, "Unsupported SignatureMethod value: " + sigMethod + " expecting: HmacSHA256 or HmacSHA1" ); - return false; + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Unsupported SignatureMethod value: " + sigMethod + " expecting: HmacSHA256 or HmacSHA1"); } + } else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - SignatureMethod"); } - else { response.sendError(530, "Missing SignatureMethod parameter" ); return false; } String[] version = request.getParameterValues( "Version" ); if ( null != version && 0 < version.length ) { if (!version[0].equals( wsdlVersion )) { - response.sendError(531, "Unsupported Version value: " + version[0] + " expecting: " + wsdlVersion ); - return false; + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Unsupported Version value: " + version[0] + " expecting: " + wsdlVersion); } + } else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Version"); } - else { response.sendError(530, "Missing Version parameter" ); return false; } String[] sigVersion = request.getParameterValues( "SignatureVersion" ); if ( null != sigVersion && 0 < sigVersion.length ) { if (!sigVersion[0].equals( "2" )) { - response.sendError(531, "Unsupported SignatureVersion value: " + sigVersion[0] + " expecting: 2" ); - return false; + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Unsupported SignatureVersion value: " + sigVersion[0] + " expecting: 2"); } } - else { response.sendError(530, "Missing SignatureVersion parameter" ); return false; } + else { + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - SignatureVersion"); + } // -> can have only one but not both { Expires | Timestamp } headers String[] expires = request.getParameterValues( "Expires" ); if ( null != expires && 0 < expires.length ) { // -> contains the date and time at which the signature included in the request EXPIRES - if (hasSignatureExpired( expires[0] )) { - response.sendError(531, "Expires parameter indicates signature has expired: " + expires[0] ); - return false; + if (hasSignatureExpired( expires[0] )) { //InvalidSecurity.RequestHasExpired + throw new EC2ServiceException( ClientError.InvalidSecurity_RequestHasExpired, + "Expires parameter indicates signature has expired: " + expires[0]); } } else { // -> contains the date and time at which the request is SIGNED String[] time = request.getParameterValues( "Timestamp" ); if ( null == time || 0 == time.length ) { - response.sendError(530, "Missing Timestamp and Expires parameter, one is required" ); - return false; + throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter -" + + " Timestamp/Expires"); } } // [B] Use the access key to get the users secret key from the cloud DB cloudSecretKey = userDao.getSecretKeyByAccessKey( cloudAccessKey ); if ( cloudSecretKey == null ) { - logger.debug("No Secret key found for Access key '" + cloudAccessKey + "' in the the EC2 service"); - throw new EC2ServiceException( ClientError.AuthFailure, "No Secret key found for Access key '" + cloudAccessKey + - "' in the the EC2 service" ); + logger.debug( "Access key '" + cloudAccessKey + "' not found in the the EC2 service "); + throw new EC2ServiceException( ClientError.AuthFailure, "Access key '" + cloudAccessKey + "' not found in the the EC2 service "); } // [C] Verify the signature @@ -2050,8 +2123,9 @@ public class EC2RestServlet extends HttpServlet { UserContext.current().initContext( cloudAccessKey, cloudSecretKey, cloudAccessKey, "REST request", null ); return true; } - else throw new PermissionDeniedException("Invalid signature"); - } + else throw new EC2ServiceException( ClientError.SignatureDoesNotMatch, + "The request signature calculated does not match the signature provided by the user."); + } /** * We check this to reduce replay attacks. diff --git a/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java b/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java index dc0d993e0b8..f6ac9711a0d 100644 --- a/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java +++ b/awsapi/src/com/cloud/bridge/service/EC2SoapServiceImpl.java @@ -53,6 +53,7 @@ import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairs; import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairsResponse; import com.cloud.bridge.service.core.ec2.EC2ImageFilterSet; import com.cloud.bridge.service.core.ec2.EC2ImageLaunchPermission; +import com.cloud.bridge.service.core.ec2.EC2ModifyInstanceAttribute; import com.cloud.bridge.service.core.ec2.EC2ResourceTag; import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroups; import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroupsResponse; @@ -96,7 +97,6 @@ import com.cloud.bridge.service.core.ec2.EC2Volume; import com.cloud.bridge.service.core.ec2.EC2VolumeFilterSet; import com.cloud.bridge.service.exception.EC2ServiceException; import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; -import com.cloud.bridge.service.exception.EC2ServiceException.ServerError; import com.cloud.bridge.util.EC2RestAuth; @@ -273,8 +273,8 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { List resourceTypeList = new ArrayList(); for (String resourceId : resourceIdList) { if (!resourceId.contains(":") || resourceId.split(":").length != 2) { - throw new EC2ServiceException( ClientError.InvalidResourceId_Format, - "Invalid Format. ResourceId format is resource-type:resource-uuid"); + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Invalid usage. ResourceId format is resource-type:resource-uuid"); } String resourceType = resourceId.split(":")[0]; if (resourceTypeList.isEmpty()) @@ -356,7 +356,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { request.setFilterSet( toAvailabiltyZonesFilterSet(fst)); } - return toDescribeAvailabilityZonesResponse( engine.handleRequest( request )); + return toDescribeAvailabilityZonesResponse( engine.describeAvailabilityZones( request )); } /** @@ -422,11 +422,11 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { EmptyElementType instanceType = diag.getInstanceType(); // -> toEC2DescribeInstances - if (null != instanceType) { - request.addInstanceId( diat.getInstanceId()); + if (null != instanceType) { + request.addInstanceId( diat.getInstanceId()); return toDescribeInstanceAttributeResponse( engine.describeInstances( request )); } - throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - only instanceType supported"); + throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - only instanceType supported"); } @@ -549,7 +549,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { request = toSnapshotFilterSet( request, fst, timeFilters ); } - return toDescribeSnapshotsResponse(engine.handleRequest(request)); + return toDescribeSnapshotsResponse(engine.describeSnapshots(request)); } public DescribeTagsResponse describeTags(DescribeTags decsribeTags) { @@ -588,7 +588,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { request = toVolumeFilterSet( request, fst, timeFilters ); } - return toDescribeVolumesResponse( engine.handleRequest( request )); + return toDescribeVolumesResponse( engine.describeVolumes( request ), engine); } public DetachVolumeResponse detachVolume(DetachVolume detachVolume) { @@ -629,6 +629,26 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { throw new EC2ServiceException( ClientError.Unsupported, "Unsupported - can only modify image description or launchPermission"); } + public ModifyInstanceAttributeResponse modifyInstanceAttribute(ModifyInstanceAttribute modifyInstanceAttribute) { + EC2ModifyInstanceAttribute request = new EC2ModifyInstanceAttribute(); + + ModifyInstanceAttributeType modifyInstanceAttribute2 = modifyInstanceAttribute.getModifyInstanceAttribute(); + ModifyInstanceAttributeTypeChoice_type0 mia = modifyInstanceAttribute2.getModifyInstanceAttributeTypeChoice_type0(); + + request.setInstanceId(modifyInstanceAttribute2.getInstanceId()); + + // we only support instanceType and userData + if (mia.getInstanceType() != null) { + request.setInstanceType(mia.getInstanceType().getValue()); + } else if (mia.getUserData() != null) { + request.setUserData(mia.getUserData().getValue()); + } else { + throw new EC2ServiceException( ClientError.MissingParamter, + "Missing required parameter - InstanceType/UserData should be provided"); + } + return toModifyInstanceAttributeResponse(engine.modifyInstanceAttribute(request)); + } + private void setAccountOrGroupList(LaunchPermissionItemType[] items, EC2ModifyImageAttribute request, String operation){ EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission(); @@ -858,26 +878,20 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { response.setUnmonitorInstancesResponse( param1 ); return response; } - - - public static DescribeImageAttributeResponse toDescribeImageAttributeResponse(EC2DescribeImagesResponse engineResponse) { - DescribeImageAttributeResponse response = new DescribeImageAttributeResponse(); - DescribeImageAttributeResponseType param1 = new DescribeImageAttributeResponseType(); - - EC2Image[] imageSet = engineResponse.getImageSet(); - if ( 0 < imageSet.length ) { - DescribeImageAttributeResponseTypeChoice_type0 param2 = new DescribeImageAttributeResponseTypeChoice_type0(); - NullableAttributeValueType param3 = new NullableAttributeValueType(); - param3.setValue( imageSet[0].getDescription()); - param2.setDescription( param3 ); - param1.setDescribeImageAttributeResponseTypeChoice_type0( param2 ); - param1.setImageId( imageSet[0].getId()); - } - - param1.setRequestId( UUID.randomUUID().toString()); - response.setDescribeImageAttributeResponse( param1 ); - return response; - } + + /** + * @param modifyInstanceAttribute + * @return + */ + public static ModifyInstanceAttributeResponse toModifyInstanceAttributeResponse(Boolean status) { + ModifyInstanceAttributeResponse miat = new ModifyInstanceAttributeResponse(); + + ModifyInstanceAttributeResponseType param = new ModifyInstanceAttributeResponseType(); + param.set_return(status); + param.setRequestId(UUID.randomUUID().toString()); + miat.setModifyInstanceAttributeResponse(param); + return miat; + } public static DescribeImageAttributeResponse toDescribeImageAttributeResponse(EC2ImageAttributes engineResponse) { DescribeImageAttributeResponse response = new DescribeImageAttributeResponse(); @@ -1311,7 +1325,7 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { } // toMethods - public static DescribeVolumesResponse toDescribeVolumesResponse( EC2DescribeVolumesResponse engineResponse ) + public static DescribeVolumesResponse toDescribeVolumesResponse( EC2DescribeVolumesResponse engineResponse, EC2Engine engine ) { DescribeVolumesResponse response = new DescribeVolumesResponse(); DescribeVolumesResponseType param1 = new DescribeVolumesResponseType(); @@ -1342,8 +1356,8 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { AttachmentSetItemResponseType param5 = new AttachmentSetItemResponseType(); param5.setVolumeId(vol.getId().toString()); param5.setInstanceId(vol.getInstanceId().toString()); - String devicePath = engine.cloudDeviceIdToDevicePath( vol.getHypervisor(), vol.getDeviceId()); - param5.setDevice( devicePath ); + String devicePath = engine.cloudDeviceIdToDevicePath( vol.getHypervisor(), vol.getDeviceId()); + param5.setDevice( devicePath ); param5.setStatus(vol.getAttachmentState()); if (vol.getAttached() == null) { param5.setAttachTime( cal ); @@ -1876,7 +1890,10 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { param1.setVolumeId( engineResponse.getId().toString()); Long volSize = new Long( engineResponse.getSize()); param1.setSize( volSize.toString()); - param1.setSnapshotId( "" ); + if (engineResponse.getSnapshotId() != null) + param1.setSnapshotId( engineResponse.getSnapshotId() ); + else + param1.setSnapshotId( "" ); param1.setAvailabilityZone( engineResponse.getZoneName()); if ( null != engineResponse.getState()) param1.setStatus( engineResponse.getState()); @@ -2503,10 +2520,6 @@ public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface { public ImportVolumeResponse importVolume(ImportVolume importVolume) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); } - - public ModifyInstanceAttributeResponse modifyInstanceAttribute(ModifyInstanceAttribute modifyInstanceAttribute) { - throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); - } public ModifySnapshotAttributeResponse modifySnapshotAttribute(ModifySnapshotAttribute modifySnapshotAttribute) { throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available"); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AddressFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AddressFilterSet.java index 1823b26218c..153fdde86df 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AddressFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AddressFilterSet.java @@ -26,6 +26,9 @@ import java.util.Map; import org.apache.log4j.Logger; +import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; + public class EC2AddressFilterSet { protected final static Logger logger = Logger.getLogger(EC2KeyPairFilterSet.class); @@ -43,16 +46,9 @@ public class EC2AddressFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) { - // Changing this to silently ignore - logger.error("Unsupported filter [" + filterName + "] - 1"); - return; - } - - if (null != value && value.equalsIgnoreCase( "null" )) { - logger.error("Unsupported filter [" + filterName + "] - 2"); - return; - } + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AvailabilityZonesFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AvailabilityZonesFilterSet.java index aa3897a4bf6..7dba8ab009e 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AvailabilityZonesFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2AvailabilityZonesFilterSet.java @@ -26,6 +26,7 @@ import java.util.Map; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; public class EC2AvailabilityZonesFilterSet { @@ -43,11 +44,9 @@ public class EC2AvailabilityZonesFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } filterSet.add( param ); } diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java index 9ac2bc68a88..1859bb807e4 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2Engine.java @@ -25,12 +25,11 @@ import java.security.SignatureException; import java.sql.SQLException; import java.text.ParseException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Set; import java.util.UUID; import javax.inject.Inject; @@ -67,7 +66,6 @@ import com.cloud.stack.models.CloudStackPasswordData; import com.cloud.stack.models.CloudStackResourceLimit; import com.cloud.stack.models.CloudStackResourceTag; import com.cloud.stack.models.CloudStackSecurityGroup; -import com.cloud.stack.models.CloudStackSecurityGroupIngress; import com.cloud.stack.models.CloudStackSnapshot; import com.cloud.stack.models.CloudStackTemplate; import com.cloud.stack.models.CloudStackTemplatePermission; @@ -227,7 +225,7 @@ public class EC2Engine extends ManagerBase { return true; } catch(Exception e) { logger.error("Validate account failed!"); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new EC2ServiceException(ClientError.AuthFailure, "User not authorised"); } } @@ -247,8 +245,9 @@ public class EC2Engine extends ManagerBase { return false; } catch( Exception e ) { logger.error( "EC2 CreateSecurityGroup - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return false; } /** @@ -266,8 +265,9 @@ public class EC2Engine extends ManagerBase { return false; } catch( Exception e ) { logger.error( "EC2 DeleteSecurityGroup - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return false; } /** @@ -276,19 +276,19 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeSecurityGroupsResponse describeSecurityGroups(EC2DescribeSecurityGroups request) - { + public EC2DescribeSecurityGroupsResponse describeSecurityGroups(EC2DescribeSecurityGroups request) { + EC2DescribeSecurityGroupsResponse response = new EC2DescribeSecurityGroupsResponse(); try { - EC2DescribeSecurityGroupsResponse response = listSecurityGroups( request.getGroupSet()); + response = listSecurityGroups( request.getGroupSet()); EC2GroupFilterSet gfs = request.getFilterSet(); - - if ( null == gfs ) - return response; - else return gfs.evaluate( response ); + if ( gfs != null ) { + response = gfs.evaluate( response ); + } } catch( Exception e ) { logger.error( "EC2 DescribeSecurityGroups - ", e); - throw new EC2ServiceException(ServerError.InternalError, "An unexpected error occurred."); + handleException(e); } + return response; } /** @@ -300,7 +300,6 @@ public class EC2Engine extends ManagerBase { */ public boolean revokeSecurityGroup( EC2AuthorizeRevokeSecurityGroup request ) { - if (null == request.getName()) throw new EC2ServiceException(ServerError.InternalError, "Name is a required parameter"); try { String[] groupSet = new String[1]; groupSet[0] = request.getName(); @@ -310,6 +309,9 @@ public class EC2Engine extends ManagerBase { EC2DescribeSecurityGroupsResponse response = listSecurityGroups( groupSet ); EC2SecurityGroup[] groups = response.getGroupSet(); + if ( groups.length == 0 ) { + throw new Exception("Unable to find security group name"); + } for (EC2SecurityGroup group : groups) { EC2IpPermission[] perms = group.getIpPermissionSet(); @@ -320,17 +322,16 @@ public class EC2Engine extends ManagerBase { } if (null == ruleId) - throw new EC2ServiceException(ClientError.InvalidGroup_NotFound, "Cannot find matching ruleid."); - + throw new Exception("Specified Ip permission is invalid"); CloudStackInfoResponse resp = getApi().revokeSecurityGroupIngress(ruleId); if (resp != null) { return resp.getSuccess(); } - return false; } catch( Exception e ) { logger.error( "EC2 revokeSecurityGroupIngress" + " - " + e.getMessage()); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); - } + handleException(e); + } + return false; } /** @@ -338,10 +339,7 @@ public class EC2Engine extends ManagerBase { * * @param request - ip permission parameters */ - public boolean authorizeSecurityGroup(EC2AuthorizeRevokeSecurityGroup request ) - { - if (null == request.getName()) throw new EC2ServiceException(ServerError.InternalError, "Name is a required parameter"); - + public boolean authorizeSecurityGroup(EC2AuthorizeRevokeSecurityGroup request ) { EC2IpPermission[] items = request.getIpPermissionSet(); try { @@ -374,7 +372,7 @@ public class EC2Engine extends ManagerBase { } } catch(Exception e) { logger.error( "EC2 AuthorizeSecurityGroupIngress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } return true; } @@ -444,13 +442,14 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeSnapshotsResponse handleRequest( EC2DescribeSnapshots request ) + public EC2DescribeSnapshotsResponse describeSnapshots( EC2DescribeSnapshots request ) { + EC2DescribeSnapshotsResponse response = new EC2DescribeSnapshotsResponse(); EC2SnapshotFilterSet sfs = request.getFilterSet(); EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet(); try { - EC2DescribeSnapshotsResponse response = listSnapshots( request.getSnapshotSet(), + response = listSnapshots( request.getSnapshotSet(), getResourceTags(tagKeyValueSet)); if (response == null) { return new EC2DescribeSnapshotsResponse(); @@ -475,17 +474,14 @@ public class EC2Engine extends ManagerBase { } snap.setVolumeSize(size); } - if ( null == sfs ) - return response; - else return sfs.evaluate( response ); - } catch( EC2ServiceException error ) { - logger.error( "EC2 DescribeSnapshots - ", error); - throw error; - + if (sfs != null) { + response = sfs.evaluate( response ); + } } catch( Exception e ) { logger.error( "EC2 DescribeSnapshots - ", e); - throw new EC2ServiceException(ServerError.InternalError, "An unexpected error occurred."); + handleException(e); } + return response; } /** @@ -495,14 +491,12 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2Snapshot createSnapshot( String volumeId ) { + EC2Snapshot ec2Snapshot = new EC2Snapshot(); try { - CloudStackSnapshot snap = getApi().createSnapshot(volumeId, null, null, null); if (snap == null) { - throw new EC2ServiceException(ServerError.InternalError, "Unable to create snapshot!"); + throw new Exception("Unable to create snapshot"); } - EC2Snapshot ec2Snapshot = new EC2Snapshot(); - ec2Snapshot.setId(snap.getId()); ec2Snapshot.setName(snap.getName()); ec2Snapshot.setType(snap.getSnapshotType()); @@ -518,12 +512,11 @@ public class EC2Engine extends ManagerBase { Long sizeInGB = vols.get(0).getSize().longValue()/1073741824; ec2Snapshot.setVolumeSize(sizeInGB); } - - return ec2Snapshot; } catch( Exception e ) { logger.error( "EC2 CreateSnapshot - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return ec2Snapshot; } /** @@ -543,8 +536,9 @@ public class EC2Engine extends ManagerBase { return false; } catch(Exception e) { logger.error( "EC2 DeleteSnapshot - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return false; } @@ -595,15 +589,11 @@ public class EC2Engine extends ManagerBase { } return false; } - } catch (Exception e) { logger.error( "EC2 modifyImageAttribute - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } - return false; - - } public EC2ImageAttributes describeImageAttribute(EC2DescribeImageAttribute request) { @@ -632,7 +622,7 @@ public class EC2Engine extends ManagerBase { } catch (Exception e) { logger.error( "EC2 describeImageAttribute - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } return imageAtts; @@ -646,18 +636,18 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2PasswordData getPasswordData(String instanceId) { + EC2PasswordData passwdData = new EC2PasswordData(); try { CloudStackPasswordData resp = getApi().getVMPassword(instanceId); - EC2PasswordData passwdData = new EC2PasswordData(); if (resp != null) { passwdData.setInstanceId(instanceId); passwdData.setEncryptedPassword(resp.getEncryptedpassword()); } - return passwdData; } catch(Exception e) { logger.error("EC2 GetPasswordData - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return passwdData; } /** @@ -667,18 +657,17 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2DescribeKeyPairsResponse describeKeyPairs( EC2DescribeKeyPairs request ) { + EC2DescribeKeyPairsResponse response = new EC2DescribeKeyPairsResponse(); try { - EC2DescribeKeyPairsResponse response = listKeyPairs(request.getKeyNames()); + response = listKeyPairs(request.getKeyNames()); EC2KeyPairFilterSet kfs = request.getKeyFilterSet(); - - if (kfs == null) - return response; - else - return kfs.evaluate(response); + if (kfs != null) + response = kfs.evaluate(response); } catch(Exception e) { logger.error("EC2 DescribeKeyPairs - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return response; } /** @@ -688,17 +677,18 @@ public class EC2Engine extends ManagerBase { * @return */ public boolean deleteKeyPair( EC2DeleteKeyPair request ) { + CloudStackInfoResponse resp = new CloudStackInfoResponse(); + String keyPairName = request.getKeyName(); try { - CloudStackInfoResponse resp = getApi().deleteSSHKeyPair(request.getKeyName(), null, null); + resp = getApi().deleteSSHKeyPair(keyPairName, null, null); if (resp == null) { throw new Exception("Ivalid CloudStack API response"); } - - return resp.getSuccess(); } catch(Exception e) { logger.error("EC2 DeleteKeyPair - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return resp.getSuccess(); } /** @@ -708,22 +698,21 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2SSHKeyPair createKeyPair(EC2CreateKeyPair request) { + String keyPairName = request.getKeyName(); + EC2SSHKeyPair response = new EC2SSHKeyPair(); try { - CloudStackKeyPair resp = getApi().createSSHKeyPair(request.getKeyName(), null, null); + CloudStackKeyPair resp = getApi().createSSHKeyPair(keyPairName, null, null); if (resp == null) { throw new Exception("Ivalid CloudStack API response"); } - - EC2SSHKeyPair response = new EC2SSHKeyPair(); response.setFingerprint(resp.getFingerprint()); response.setKeyName(resp.getName()); response.setPrivateKey(resp.getPrivatekey()); - - return response; } catch (Exception e) { logger.error("EC2 CreateKeyPair - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return response; } /** @@ -733,22 +722,20 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2SSHKeyPair importKeyPair( EC2ImportKeyPair request ) { + EC2SSHKeyPair response = new EC2SSHKeyPair(); try { CloudStackKeyPair resp = getApi().registerSSHKeyPair(request.getKeyName(), request.getPublicKeyMaterial()); if (resp == null) { throw new Exception("Ivalid CloudStack API response"); } - - EC2SSHKeyPair response = new EC2SSHKeyPair(); response.setFingerprint(resp.getFingerprint()); response.setKeyName(resp.getName()); response.setPrivateKey(resp.getPrivatekey()); - - return response; } catch (Exception e) { logger.error("EC2 ImportKeyPair - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return response; } /** @@ -758,18 +745,17 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2DescribeAddressesResponse describeAddresses( EC2DescribeAddresses request ) { + EC2DescribeAddressesResponse response = new EC2DescribeAddressesResponse(); try { - EC2DescribeAddressesResponse response = listAddresses(request.getPublicIpsSet()); + response = listAddresses(request.getPublicIpsSet()); EC2AddressFilterSet afs = request.getFilterSet(); - - if (afs ==null) - return response; - else - return afs.evaluate(response); + if (afs != null) + response = afs.evaluate(response); } catch(Exception e) { logger.error("EC2 DescribeAddresses - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return response; } /** @@ -782,7 +768,7 @@ public class EC2Engine extends ManagerBase { try { List cloudIps = getApi().listPublicIpAddresses(null, null, null, null, null, request.getPublicIp(), null, null, null); if (cloudIps == null) - throw new EC2ServiceException(ServerError.InternalError, "Specified ipAddress doesn't exist"); + throw new Exception("Specified ipAddress doesn't exist"); CloudStackIpAddress cloudIp = cloudIps.get(0); CloudStackInfoResponse resp = getApi().disassociateIpAddress(cloudIp.getId()); if (resp != null) { @@ -790,7 +776,7 @@ public class EC2Engine extends ManagerBase { } } catch(Exception e) { logger.error("EC2 ReleaseAddress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } return false; } @@ -805,13 +791,13 @@ public class EC2Engine extends ManagerBase { try { List cloudIps = getApi().listPublicIpAddresses(null, null, null, null, null, request.getPublicIp(), null, null, null); if (cloudIps == null) - throw new EC2ServiceException(ServerError.InternalError, "Specified ipAddress doesn't exist"); + throw new Exception("Specified ipAddress doesn't exist"); CloudStackIpAddress cloudIp = cloudIps.get(0); List vmList = getApi().listVirtualMachines(null, null, true, null, null, null, null, request.getInstanceId(), null, null, null, null, null, null, null, null, null); if (vmList == null || vmList.size() == 0) { - throw new EC2ServiceException(ServerError.InternalError, "Specified instance-id doesn't exist"); + throw new Exception("Instance not found"); } CloudStackUserVm cloudVm = vmList.get(0); @@ -821,7 +807,7 @@ public class EC2Engine extends ManagerBase { } } catch(Exception e) { logger.error( "EC2 AssociateAddress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } return false; } @@ -836,7 +822,7 @@ public class EC2Engine extends ManagerBase { try { List cloudIps = getApi().listPublicIpAddresses(null, null, null, null, null, request.getPublicIp(), null, null, null); if (cloudIps == null) - throw new EC2ServiceException(ServerError.InternalError, "Specified ipAddress doesn't exist"); + throw new Exception("Specified ipAddress doesn't exist"); CloudStackIpAddress cloudIp = cloudIps.get(0); CloudStackInfoResponse resp = getApi().disableStaticNat(cloudIp.getId()); @@ -845,7 +831,7 @@ public class EC2Engine extends ManagerBase { } } catch(Exception e) { logger.error( "EC2 DisassociateAddress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } return false; } @@ -856,10 +842,9 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2Address allocateAddress() - { + public EC2Address allocateAddress() { + EC2Address ec2Address = new EC2Address(); try { - EC2Address ec2Address = new EC2Address(); // this gets our networkId CloudStackAccount caller = getCurrentAccount(); @@ -881,12 +866,11 @@ public class EC2Engine extends ManagerBase { } else { ec2Address.setIpAddress(resp.getIpAddress()); } - - return ec2Address; } catch(Exception e) { logger.error( "EC2 AllocateAddress - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return ec2Address; } /** @@ -896,10 +880,8 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeImagesResponse describeImages(EC2DescribeImages request) - { + public EC2DescribeImagesResponse describeImages(EC2DescribeImages request) { EC2DescribeImagesResponse images = new EC2DescribeImagesResponse(); - try { String[] templateIds = request.getImageSet(); EC2ImageFilterSet ifs = request.getFilterSet(); @@ -911,14 +893,13 @@ public class EC2Engine extends ManagerBase { images = listTemplates(s, images); } } - if (ifs == null) - return images; - else + if (ifs != null) return ifs.evaluate(images); } catch( Exception e ) { logger.error( "EC2 DescribeImages - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return images; } /** @@ -938,10 +919,9 @@ public class EC2Engine extends ManagerBase { */ public EC2CreateImageResponse createImage(EC2CreateImage request) { - EC2CreateImageResponse response = null; + EC2CreateImageResponse response = new EC2CreateImageResponse(); boolean needsRestart = false; String volumeId = null; - try { // [A] Creating a template from a VM volume should be from the ROOT volume // Also for this to work the VM must be in a Stopped state so we 'reboot' it if its not @@ -954,7 +934,7 @@ public class EC2Engine extends ManagerBase { if (vmState.equalsIgnoreCase( "running" ) || vmState.equalsIgnoreCase( "starting" )) { needsRestart = true; if (!stopVirtualMachine( request.getInstanceId() )) - throw new EC2ServiceException(ClientError.IncorrectState, "CreateImage - instance must be in a stopped state"); + throw new Exception("Instance must be in a stopped state"); } volumeId = vol.getId(); break; @@ -975,25 +955,22 @@ public class EC2Engine extends ManagerBase { CloudStackTemplate resp = getApi().createTemplate((request.getDescription() == null ? "" : request.getDescription()), request.getName(), osTypeId, null, null, null, null, null, null, volumeId); if (resp == null || resp.getId() == null) { - throw new EC2ServiceException(ServerError.InternalError, "An upexpected error occurred."); + throw new Exception("Image couldn't be created"); } //if template was created succesfully, create the new image response - response = new EC2CreateImageResponse(); response.setId(resp.getId()); // [C] If we stopped the virtual machine now we need to restart it if (needsRestart) { - if (!startVirtualMachine( request.getInstanceId() )) - throw new EC2ServiceException(ServerError.InternalError, - "CreateImage - restarting instance " + request.getInstanceId() + " failed"); + if (!startVirtualMachine( request.getInstanceId() )) + throw new Exception("Failed to start the stopped instance"); } - return response; - } catch( Exception e ) { logger.error( "EC2 CreateImage - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return response; } /** @@ -1002,13 +979,9 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2CreateImageResponse registerImage(EC2RegisterImage request) - { + public EC2CreateImageResponse registerImage(EC2RegisterImage request) { + EC2CreateImageResponse image = new EC2CreateImageResponse(); try { - CloudStackAccount caller = getCurrentAccount(); - if (null == request.getName()) - throw new EC2ServiceException(ClientError.Unsupported, "Missing parameter - name"); - List templates = getApi().registerTemplate((request.getDescription() == null ? request.getName() : request.getDescription()), request.getFormat(), request.getHypervisor(), request.getName(), toOSTypeId(request.getOsTypeName()), request.getLocation(), toZoneId(request.getZoneName(), null), null, null, null, null, null, null, null, null, null); @@ -1016,17 +989,16 @@ public class EC2Engine extends ManagerBase { // technically we will only ever register a single template... for (CloudStackTemplate template : templates) { if (template != null && template.getId() != null) { - EC2CreateImageResponse image = new EC2CreateImageResponse(); image.setId(template.getId().toString()); return image; } } } - return null; } catch( Exception e ) { logger.error( "EC2 RegisterImage - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return image; } /** @@ -1044,8 +1016,9 @@ public class EC2Engine extends ManagerBase { return resp.getSuccess(); } catch( Exception e ) { logger.error( "EC2 DeregisterImage - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return false; } /** @@ -1055,14 +1028,16 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2DescribeInstancesResponse describeInstances(EC2DescribeInstances request ) { + EC2DescribeInstancesResponse response = new EC2DescribeInstancesResponse(); try { EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet(); - return listVirtualMachines( request.getInstancesSet(), request.getFilterSet(), + response = listVirtualMachines( request.getInstancesSet(), request.getFilterSet(), getResourceTags(tagKeyValueSet)); } catch( Exception e ) { logger.error( "EC2 DescribeInstances - " ,e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return response; } /** @@ -1071,22 +1046,18 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeAvailabilityZonesResponse handleRequest(EC2DescribeAvailabilityZones request) { + public EC2DescribeAvailabilityZonesResponse describeAvailabilityZones(EC2DescribeAvailabilityZones request) { + EC2DescribeAvailabilityZonesResponse availableZones = new EC2DescribeAvailabilityZonesResponse(); try { - EC2DescribeAvailabilityZonesResponse availableZones = listZones(request.getZoneSet(), null); + availableZones = listZones(request.getZoneSet(), null); EC2AvailabilityZonesFilterSet azfs = request.getFilterSet(); - if ( null == azfs ) - return availableZones; - else - return azfs.evaluate(availableZones); - } catch( EC2ServiceException error ) { - logger.error( "EC2 DescribeAvailabilityZones - ", error); - throw error; - + if ( azfs != null ) + availableZones = azfs.evaluate(availableZones); } catch( Exception e ) { logger.error( "EC2 DescribeAvailabilityZones - " ,e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return availableZones; } /** @@ -1095,7 +1066,7 @@ public class EC2Engine extends ManagerBase { * @param request * @return */ - public EC2DescribeVolumesResponse handleRequest( EC2DescribeVolumes request ) { + public EC2DescribeVolumesResponse describeVolumes( EC2DescribeVolumes request ) { EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse(); EC2VolumeFilterSet vfs = request.getFilterSet(); EC2TagKeyValue[] tagKeyValueSet = request.getResourceTagSet(); @@ -1107,14 +1078,13 @@ public class EC2Engine extends ManagerBase { for (String s : volumeIds) volumes = listVolumes(s, null, volumes, getResourceTags(tagKeyValueSet) ); } - - if ( null == vfs ) - return volumes; - else return vfs.evaluate( volumes ); + if ( vfs != null ) + volumes = vfs.evaluate( volumes ); } catch( Exception e ) { logger.error( "EC2 DescribeVolumes - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return volumes; } /** @@ -1124,10 +1094,9 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2Volume attachVolume( EC2Volume request ) { + EC2Volume resp = new EC2Volume(); try { request.setDeviceId(mapDeviceToCloudDeviceId(request.getDevice())); - EC2Volume resp = new EC2Volume(); - CloudStackVolume vol = getApi().attachVolume(request.getId(), request.getInstanceId(), request.getDeviceId()); if(vol != null) { resp.setAttached(vol.getAttached()); @@ -1144,13 +1113,12 @@ public class EC2Engine extends ManagerBase { resp.setVMState(vol.getVirtualMachineState()); resp.setAttachmentState(mapToAmazonVolumeAttachmentState(vol.getVirtualMachineState())); resp.setZoneName(vol.getZoneName()); - return resp; } - throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occurred." ); } catch( Exception e ) { - logger.error( "EC2 AttachVolume 2 - ", e); - throw new EC2ServiceException( ServerError.InternalError, e.getMessage() != null ? e.getMessage() : e.toString()); - } + logger.error( "EC2 AttachVolume - ", e); + handleException(e); + } + return resp; } /** @@ -1160,10 +1128,27 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2Volume detachVolume(EC2Volume request) { + EC2Volume resp = new EC2Volume(); try { - CloudStackVolume vol = getApi().detachVolume(null, request.getId(), null); - EC2Volume resp = new EC2Volume(); + // verifying if instanceId and deviceId provided is valid + EC2DescribeVolumesResponse volumes = new EC2DescribeVolumesResponse(); + volumes = listVolumes(request.getId(), null, volumes, null); + if (volumes != null) { + EC2Volume[] volumeSet = volumes.getVolumeSet(); + if (request.getInstanceId() != null) { + if ( !request.getInstanceId().equalsIgnoreCase(volumeSet[0].getInstanceId()) ) + throw new Exception("Volume is not attached to the Instance"); + } + if (request.getDevice() != null) { + String devicePath = null; + if ( volumeSet[0].getDeviceId() != null ) + devicePath = cloudDeviceIdToDevicePath( volumeSet[0].getHypervisor(), volumeSet[0].getDeviceId()); + if ( !request.getDevice().equalsIgnoreCase(devicePath) ) + throw new Exception("Volume is not attached to the Device"); + } + } + CloudStackVolume vol = getApi().detachVolume(null , request.getId(), null); if(vol != null) { resp.setAttached(vol.getAttached()); resp.setCreated(vol.getCreated()); @@ -1178,14 +1163,12 @@ public class EC2Engine extends ManagerBase { resp.setType(vol.getVolumeType()); resp.setVMState(vol.getVirtualMachineState()); resp.setZoneName(vol.getZoneName()); - return resp; } - - throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occurred." ); } catch( Exception e ) { logger.error( "EC2 DetachVolume - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); - } + handleException(e); + } + return resp; } /** @@ -1195,9 +1178,8 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2Volume createVolume( EC2CreateVolume request ) { + EC2Volume resp = new EC2Volume(); try { - - CloudStackAccount caller = getCurrentAccount(); // -> put either snapshotid or diskofferingid on the request String snapshotId = request.getSnapshotId(); Long size = request.getSize(); @@ -1216,7 +1198,6 @@ public class EC2Engine extends ManagerBase { // // -> no volume name is given in the Amazon request but is required in the cloud API CloudStackVolume vol = getApi().createVolume(UUID.randomUUID().toString(), null, diskOfferingId, null, size, snapshotId, toZoneId(request.getZoneName(), null)); if (vol != null) { - EC2Volume resp = new EC2Volume(); resp.setAttached(vol.getAttached()); resp.setCreated(vol.getCreated()); // resp.setDevice(); @@ -1231,13 +1212,12 @@ public class EC2Engine extends ManagerBase { resp.setVMState(vol.getVirtualMachineState()); resp.setAttachmentState("detached"); resp.setZoneName(vol.getZoneName()); - return resp; } - return null; } catch( Exception e ) { logger.error( "EC2 CreateVolume - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); - } + handleException(e); + } + return resp; } /** @@ -1251,14 +1231,12 @@ public class EC2Engine extends ManagerBase { CloudStackInfoResponse resp = getApi().deleteVolume(request.getId()); if(resp != null) { request.setState("deleted"); - return request; } - - throw new EC2ServiceException(ServerError.InternalError, "An unexpected error occurred."); } catch( Exception e ) { - logger.error( "EC2 DeleteVolume 2 - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); - } + logger.error( "EC2 DeleteVolume - ", e); + handleException(e); + } + return request; } /** @@ -1295,9 +1273,9 @@ public class EC2Engine extends ManagerBase { return true; } catch (Exception e){ logger.error( "EC2 Create/Delete Tags - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? - e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return false; } /** @@ -1307,11 +1285,11 @@ public class EC2Engine extends ManagerBase { * @return */ public EC2DescribeTagsResponse describeTags (EC2DescribeTags request) { + EC2DescribeTagsResponse tagResponse = new EC2DescribeTagsResponse(); try { - EC2DescribeTagsResponse tagResponse = new EC2DescribeTagsResponse(); + tagResponse = new EC2DescribeTagsResponse(); List resourceTagList = getApi().listTags(null, null, null, true, null); - List tagList = new ArrayList(); if (resourceTagList != null && resourceTagList.size() > 0) { for (CloudStackResourceTag resourceTag: resourceTagList) { EC2ResourceTag tag = new EC2ResourceTag(); @@ -1325,14 +1303,13 @@ public class EC2Engine extends ManagerBase { } EC2TagsFilterSet tfs = request.getFilterSet(); - if (tfs == null) - return tagResponse; - else - return tfs.evaluate(tagResponse); + if (tfs != null) + tagResponse = tfs.evaluate(tagResponse); } catch(Exception e) { logger.error("EC2 DescribeTags - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + handleException(e); } + return tagResponse; } /** @@ -1362,13 +1339,14 @@ public class EC2Engine extends ManagerBase { // -> if some specified VMs where not found we have to tell the caller if (instanceSet.length != vms.length) - throw new EC2ServiceException(ClientError.InvalidAMIID_NotFound, "One or more instanceIds do not exist, other instances rebooted."); + throw new Exception("One or more instanceIds do not exist, other instances rebooted."); return true; } catch( Exception e ) { logger.error( "EC2 RebootInstances - ", e ); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return false; } /** @@ -1384,15 +1362,13 @@ public class EC2Engine extends ManagerBase { int countCreated = 0; try { - CloudStackAccount caller = getCurrentAccount(); - // ugly... canCreateInstances = calculateAllowedInstances(); if (-1 == canCreateInstances) canCreateInstances = request.getMaxCount(); if (canCreateInstances < request.getMinCount()) { logger.info( "EC2 RunInstances - min count too big (" + request.getMinCount() + "), " + canCreateInstances + " left to allocate"); - throw new EC2ServiceException(ClientError.InstanceLimitExceeded ,"Only " + canCreateInstances + " instance(s) left to allocate"); + throw new Exception("Min Count is greater than the number of instances left to allocate"); } if ( canCreateInstances < request.getMaxCount()) @@ -1408,7 +1384,7 @@ public class EC2Engine extends ManagerBase { CloudStackServiceOfferingVO svcOffering = getCSServiceOfferingId(instanceType); if(svcOffering == null){ logger.info("No ServiceOffering found to be defined by name, please contact the administrator "+instanceType ); - throw new EC2ServiceException(ClientError.Unsupported, "instanceType: [" + instanceType + "] not found!"); + throw new Exception("instanceType not found"); } // zone stuff @@ -1417,7 +1393,7 @@ public class EC2Engine extends ManagerBase { List zones = getApi().listZones(null, null, zoneId, null); if (zones == null || zones.size() == 0) { logger.info("EC2 RunInstances - zone [" + request.getZoneName() + "] not found!"); - throw new EC2ServiceException(ClientError.InvalidZone_NotFound, "ZoneId [" + request.getZoneName() + "] not found!"); + throw new Exception("zone not found"); } // we choose first zone? CloudStackZone zone = zones.get(0); @@ -1467,19 +1443,17 @@ public class EC2Engine extends ManagerBase { logger.error("Failed to deploy VM number: "+ (i+1) +" due to error: "+e.getMessage()); break; } - } - + } if (0 == countCreated) { // TODO, we actually need to destroy left-over VMs when the exception is thrown - throw new EC2ServiceException(ServerError.InternalError, "Failed to deploy instances" ); + throw new Exception("Insufficient Instance Capacity"); } logger.debug("Could deploy "+ countCreated + " VM's successfully"); - - return instances; } catch( Exception e ) { logger.error( "EC2 RunInstances - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return instances; } /** @@ -1515,11 +1489,11 @@ public class EC2Engine extends ManagerBase { } instances.addInstance(vm); } - return instances; } catch( Exception e ) { logger.error( "EC2 StartInstances - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + handleException(e); } + return instances; } /** @@ -1566,11 +1540,48 @@ public class EC2Engine extends ManagerBase { instances.addInstance(vm); } } - return instances; } catch( Exception e ) { logger.error( "EC2 StopInstances - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() + ", might already be destroyed" : "An unexpected error occurred."); + handleException(e); } + return instances; + } + + /** + * @param request + * @return + * @throws Exception + */ + public boolean modifyInstanceAttribute(EC2ModifyInstanceAttribute request) { + boolean status = true; + String instanceId = request.getInstanceId(); + try { + // AWS requires VM to be in stopped state to modify 'InstanceType' and 'UserData' + EC2DescribeInstancesResponse vmResponse = new EC2DescribeInstancesResponse(); + vmResponse = lookupInstances(instanceId, vmResponse, null); + EC2Instance[] instances = vmResponse.getInstanceSet(); + if ( !instances[0].getState().equalsIgnoreCase("stopped")) { + throw new Exception("Cannot modify, instance should be in stopped state"); + } + + if (request.getInstanceType() != null) { + String instanceType = request.getInstanceType(); + CloudStackServiceOfferingVO svcOffering = getCSServiceOfferingId(instanceType); + if (svcOffering == null) + throw new Exception("instanceType not found"); + CloudStackUserVm userVm = getApi().changeServiceForVirtualMachine(instanceId, svcOffering.getId()); + status = (userVm != null); + } + if (status != false && request.getUserData() != null) { + CloudStackUserVm userVm = getApi().updateVirtualMachine(instanceId, null, null, null, + null, request.getUserData()); + status = (userVm != null); + } + } catch (Exception e) { + logger.error("ModifyInstanceAttribute - ", e); + handleException(e); + } + return status; } /** @@ -1719,7 +1730,7 @@ public class EC2Engine extends ManagerBase { zones = listZones(interestedZones, domainId); if (zones == null || zones.getAvailabilityZoneSet().length == 0) - throw new EC2ServiceException(ClientError.InvalidParameterValue, "Unknown zoneName value - " + zoneName); + throw new Exception("Unknown zoneName value"); EC2AvailabilityZone[] zoneSet = zones.getAvailabilityZoneSet(); return zoneSet[0].getId(); @@ -1731,15 +1742,22 @@ public class EC2Engine extends ManagerBase { * */ - private CloudStackServiceOfferingVO getCSServiceOfferingId(String instanceType){ + private CloudStackServiceOfferingVO getCSServiceOfferingId(String instanceType) throws Exception { try { - if (null == instanceType) instanceType = "m1.small"; + // list of valid values for AWS EC2 instanceType + String[] validInstanceTypes = {"t1.micro", "m1.small", "m1.medium", "m1.large", "m1.xlarge", + "c1.medium", "c1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", + "m3.xlarge", "m3.2xlarge", "hi1.4xlarge", "cc1.4xlarge", "cg1.4xlarge", "cc2.8xlarge"}; + if (instanceType == null) + instanceType = "m1.small"; // default value + else if ( !Arrays.asList(validInstanceTypes).contains(instanceType)) { + throw new Exception("Specified instance type is invalid"); + } return scvoDao.getSvcOfferingByName(instanceType); - } catch(Exception e) { logger.error( "Error while retrieving ServiceOffering information by name - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception("No ServiceOffering found to be defined by name"); } } @@ -1751,7 +1769,7 @@ public class EC2Engine extends ManagerBase { * @return A valid value for the Amazon defined instanceType * @throws SQLException, ClassNotFoundException, IllegalAccessException, InstantiationException */ - private String serviceOfferingIdToInstanceType( String serviceOfferingId ){ + private String serviceOfferingIdToInstanceType( String serviceOfferingId ) throws Exception { try{ CloudStackServiceOfferingVO offering = scvoDao.getSvcOfferingById(serviceOfferingId); //dao.getSvcOfferingById(serviceOfferingId); @@ -1762,8 +1780,8 @@ public class EC2Engine extends ManagerBase { return offering.getName(); } catch(Exception e) { - logger.error( "sError while retrieving ServiceOffering information by id - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + logger.error( "Error while retrieving ServiceOffering information by id - ", e); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -1784,7 +1802,7 @@ public class EC2Engine extends ManagerBase { return null; } catch(Exception e) { logger.error( "List OS Types - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -1898,7 +1916,7 @@ public class EC2Engine extends ManagerBase { }else{ if(instanceId != null){ //no such instance found - throw new EC2ServiceException(ServerError.InternalError, "Instance:" + instanceId + " not found"); + throw new Exception("Instance not found"); } } return instances; @@ -1915,7 +1933,7 @@ public class EC2Engine extends ManagerBase { * @return the same object passed in as the "images" parameter modified with one or more * EC2Image objects loaded. */ - private EC2DescribeImagesResponse listTemplates( String templateId, EC2DescribeImagesResponse images ) throws EC2ServiceException { + private EC2DescribeImagesResponse listTemplates( String templateId, EC2DescribeImagesResponse images ) throws Exception { try { List result = new ArrayList(); @@ -1985,7 +2003,7 @@ public class EC2Engine extends ManagerBase { return images; } catch(Exception e) { logger.error( "List Templates - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2036,7 +2054,7 @@ public class EC2Engine extends ManagerBase { return groupSet; } catch(Exception e) { logger.error( "List Security Groups - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2068,7 +2086,7 @@ public class EC2Engine extends ManagerBase { return keyPairSet; } catch(Exception e) { logger.error( "List Keypairs - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2101,7 +2119,7 @@ public class EC2Engine extends ManagerBase { return addressSet; } catch(Exception e) { logger.error( "List Addresses - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception(e.getMessage() != null ? e.getMessage() : e.toString()); } } @@ -2148,7 +2166,7 @@ public class EC2Engine extends ManagerBase { return snapshotSet; } catch(Exception e) { logger.error( "List Snapshots - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception(e.getMessage() != null ? e.getMessage() : e.toString()); } } @@ -2298,7 +2316,7 @@ public class EC2Engine extends ManagerBase { } // if we get this far and haven't returned already return an error - throw new EC2ServiceException(ServerError.InternalError, "Unable to find an appropriate network for account " + caller.getName()); + throw new Exception("Unable to find an appropriate network for account "); } /** @@ -2344,12 +2362,12 @@ public class EC2Engine extends ManagerBase { /** * Finds the defaultZone marked for the account */ - private String getDefaultZoneId(String accountId) { + private String getDefaultZoneId(String accountId) throws Exception { try { return accDao.getDefaultZoneId(accountId); } catch(Exception e) { logger.error( "Error while retrieving Account information by id - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage()); + throw new Exception("Unable to retrieve account account information"); } } @@ -2400,7 +2418,7 @@ public class EC2Engine extends ManagerBase { * @param device string * @return deviceId value */ - private String mapDeviceToCloudDeviceId( String device ) + private String mapDeviceToCloudDeviceId( String device ) throws Exception { if (device.equalsIgnoreCase( "/dev/sdb" )) return "1"; else if (device.equalsIgnoreCase( "/dev/sdc" )) return "2"; @@ -2429,7 +2447,7 @@ public class EC2Engine extends ManagerBase { else if (device.equalsIgnoreCase( "xvdi" )) return "8"; else if (device.equalsIgnoreCase( "xvdj" )) return "9"; - else throw new EC2ServiceException( ClientError.Unsupported, device + " is not supported" ); + else throw new Exception("Device is not supported"); } /** @@ -2529,7 +2547,7 @@ public class EC2Engine extends ManagerBase { return resp != null; } catch(Exception e) { logger.error( "StopVirtualMachine - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2548,7 +2566,7 @@ public class EC2Engine extends ManagerBase { return resp != null; } catch(Exception e) { logger.error("StartVirtualMachine - ", e); - throw new EC2ServiceException(ServerError.InternalError, e.getMessage() != null ? e.getMessage() : "An unexpected error occurred."); + throw new Exception( e.getMessage() != null ? e.getMessage() : e.toString() ); } } @@ -2577,4 +2595,269 @@ public class EC2Engine extends ManagerBase { } return resourceTags; } + + private void handleException( Exception e) { + String[] error = e.getMessage().split("Error Code - "); + String errorMessage = error[0]; + if (error.length == 2) { // error code has been supplied + int errorCode = Integer.parseInt(error[1]); + if (errorCode == 431) { + if ( errorMessage.contains("Object vm_instance(uuid:") && errorMessage.contains(") does not exist") ) { + throw new EC2ServiceException( ClientError.InvalidInstanceID_NotFound, + "Specified Instance ID does not exist"); + } else if ( errorMessage.contains("Unable to find security group by name") || + errorMessage.contains("Unable to find security group") || + ( errorMessage.contains("Object security_group(uuid:") && errorMessage.contains(") does not exist") ) || + errorMessage.contains("Unable to find group by name ") ) { + throw new EC2ServiceException( ClientError.InvalidGroup_NotFound, + "Specified Security Group does not exist"); + } else if ( errorMessage.contains("Invalid port numbers") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified Port value is invalid"); + } else if (errorMessage.contains("Nonexistent account") && errorMessage.contains("when trying to authorize security group rule for security group") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified account doesn't exist"); + } else if ( errorMessage.contains("Nonexistent group") && errorMessage.contains("unable to authorize security group rule") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified source security group doesn't exist"); + } else if ( errorMessage.contains("Invalid protocol") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified protocol is invalid"); + } else if ( errorMessage.contains("is an Invalid CIDR") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "Specified CIDR is invalid"); + }else if ( errorMessage.contains("Nonexistent account") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified Account name is invalid"); + } else if ( errorMessage.contains("Object volumes(uuid:") && errorMessage.contains(") does not exist") ) { + throw new EC2ServiceException( ClientError.InvalidVolume_NotFound, + "Specified Volume ID doesn't exist"); + } else if ( errorMessage.contains("Object snapshots(uuid:") && errorMessage.contains(") does not exist") ) { + throw new EC2ServiceException( ClientError.InvalidSnapshot_NotFound, + "Specified Snapshot ID doesn't exist"); + } else if ( (errorMessage.contains("A key pair with name '") && errorMessage.contains("' does not exist")) || + (errorMessage.contains("A key pair with name '") && errorMessage.contains("' was not found")) ) { + throw new EC2ServiceException( ClientError.InvalidKeyPair_NotFound, + "Specified Key pair name is invalid"); + } else if ( errorMessage.contains("A key pair with name '") && errorMessage.contains("' already exists") ) { + throw new EC2ServiceException( ClientError.InvalidKeyPair_Duplicate, + "Specified Key pair already exists"); + } else if ( errorMessage.contains("Unknown zoneName value") ) { + throw new EC2ServiceException( ClientError.InvalidZone_NotFound, + "Specified AvailabilityZone name is invalid"); + } else if ( errorMessage.contains("specify a volume that is not attached to any VM") ) { + throw new EC2ServiceException( ClientError.DependencyViolation, + "Specified Volume is attached to a VM"); + } else if ( errorMessage.contains("Object vm_template(uuid: ")&& errorMessage.contains(") does not exist") ) { + throw new EC2ServiceException( ClientError.InvalidAMIID_NotFound, + "Specified Image ID does not exist"); + } else if ( errorMessage.contains("unable to find template by id") ) { + throw new EC2ServiceException( ClientError.InvalidAMIID_NotFound, + "Specified Image ID does not exist"); + } else if ( errorMessage.contains("a group with name") && errorMessage.contains("already exists") ) { + throw new EC2ServiceException( ClientError.InvalidGroup_Duplicate, + "Specified Security Group already exists"); + } else if ( errorMessage.contains("specified volume is not attached to a VM") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Specified volume is not in the correct state 'attached' for detachment"); + } else if ( errorMessage.contains("Snapshot with specified snapshotId is not in BackedUp state yet and can't be used for volume creation") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Specified snapshot is not in the correct state 'completed' for volume creation"); + } else if ( errorMessage.contains("Can't delete snapshotshot 4 due to it is not in BackedUp Status") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Specified snapshot is not in the correct state 'completed' for deletion"); + } else if ( errorMessage.contains("Public key is invalid") ) { + throw new EC2ServiceException( ClientError.InvalidKeyPair_Format, + "Format of the specified key is invalid"); + } else if ( errorMessage.contains("Invalid resource type") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified resourceId is invalid"); + } else if ( errorMessage.contains("Unable to find tags by parameters specified") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified resourceTag for the specified resourceId doesn't exist"); + } else if ( errorMessage.contains("Failed to enable static nat for the ip address with specified ipId " + + "as vm with specified vmId is already associated with specified currentIp") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified publicIp is already associated to the specified VM"); + } else if ( errorMessage.contains("Specified IP address id is not associated with any vm Id") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified publicIp is not associated to any VM"); + } else if ( errorMessage.contains("specify a VM that is either running or stopped") ) { + throw new EC2ServiceException( ClientError.IncorrectInstanceState, + "Unable to attach. Specified instances is in an incorrect state"); + } else if ( errorMessage.contains("specify a valid data volume") ) { + throw new EC2ServiceException( ClientError.InvalidVolume_NotFound, + "Specified volume doen't exist"); + } else if ( errorMessage.contains("VolumeId is not in Ready state, but in state Allocated. Cannot take snapshot") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Cannot take snapshot. Specified volume is not in the correct state"); + } else if ( errorMessage.contains("Can't delete snapshot") && errorMessage.contains("it is not in BackedUp Status") ) { + throw new EC2ServiceException( ClientError.IncorrectState, + "Cannot delete snapshot. Specified snapshot is not in the correct state"); + } else if ( errorMessage.contains("Invalid port range") ) { + throw new EC2ServiceException( ClientError.InvalidPermission_Malformed, + "The specified port range is invalid"); + } else if ( errorMessage.contains("specify a valid User VM") ) { + throw new EC2ServiceException( ClientError.InvalidInstanceID_NotFound, + "Specified instance is invalid"); + } else if ( errorMessage.contains("No password for VM with specified id found") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "No password for VM with the specified id found"); + } else if ( errorMessage.contains("make sure the virtual machine is stopped and not in an error state before upgrading") ) { + throw new EC2ServiceException( ClientError.IncorrectInstanceState, + "Unable to modify. Specified instances is not in the correct state 'Stopped'"); + } else if ( errorMessage.contains("Not upgrading vm") && errorMessage.contains("it already has the" + + " requested service offering") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Unable to modify. Specified instance already has the requested instanceType"); + } + // Can't enable static, ip address with specified id is a sourceNat ip address ? + else { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "The value supplied for a parameter is invalid"); + } + } + else if (errorCode == 536) { + if ( errorMessage.contains("Cannot delete group when it's in use by virtual machines") ) { + throw new EC2ServiceException( ClientError.InvalidGroup_InUse, + "Group is in use by a virtual machine"); + } else { + throw new EC2ServiceException( ClientError.DependencyViolation, + "Specified resource is in use"); + } + } + else if (errorCode == 531) { + if ( errorMessage.contains("Acct") && errorMessage.contains("does not have permission to launch" + + " instances from Tmpl") ) { + throw new EC2ServiceException( ClientError.AuthFailure, + "User not authorized to operate on the specified AMI"); + } else { + throw new EC2ServiceException( ClientError.AuthFailure, "User not authorized"); + } + } + else if (errorCode == 530) { + if ( errorMessage.contains("deviceId") && errorMessage.contains("is used by VM") ) { + throw new EC2ServiceException( ClientError.InvalidDevice_InUse, + "Specified Device is already being used by the VM"); + } else if (errorMessage.contains("Entity already exists") ){ + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "Specified resource tag already exists"); + } else if ( errorMessage.contains("Template") && errorMessage.contains("has not been completely downloaded") ){ + throw new EC2ServiceException( ClientError.InvalidAMIID_NotFound, + "Specified ImageId is unavailable"); + } else if ( errorMessage.contains("cannot stop VM") && errorMessage.contains("when it is in state Starting") ){ + throw new EC2ServiceException( ClientError.IncorrectInstanceState, + "Unable to stop. One or more of the specified instances is in an incorrect state 'pending'"); + } else if ( errorMessage.contains("Failed to authorize security group ingress rule(s)") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, "Specified Ip-permission is invalid" + + " or the Ip-permission already exists"); + } else if ( errorMessage.contains("Failed to reboot vm instance") ) { + throw new EC2ServiceException(ClientError.IncorrectInstanceState, + "Unable to reboot. One or more of the specified instances is in an incorrect state"); + } else if ( errorMessage.contains("specify a template that is not currently being downloaded") ) { + throw new EC2ServiceException(ClientError.IncorrectState, + "Unable to deregister. Image is not in the correct state 'available'"); + } else { + throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occured"); + } + } + else if (errorCode == 534) { + if ( errorMessage.contains("Maximum number of resources of type 'volume' for account") + && errorMessage.contains("has been exceeded") ) { + throw new EC2ServiceException( ClientError.VolumeLimitExceeded, + "You have reached the limit on the number of volumes that can be created"); + } else if ( errorMessage.contains("Maximum number of resources of type 'public_ip' for account") + && errorMessage.contains("has been exceeded") ) { + throw new EC2ServiceException( ClientError.AddressLimitExceeded, + "You have reached the limit on the number of elastic ip addresses your account can have"); + } else if ( errorMessage.contains("Unable to apply save userdata entry on router") ) { + throw new EC2ServiceException( ClientError.InvalidParameterValue, + "The value supplied for parameter UserData is invalid"); + } else { + throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occured"); + } + } + else if (errorCode == 533) { + if ( errorMessage.contains("Unable to create a deployment for VM") ) { + throw new EC2ServiceException( ClientError.InsufficientInstanceCapacity, + "There is insufficient capacity available to deploy a VM"); + } else if ( errorMessage.contains("Insufficient address capacity") ) { + throw new EC2ServiceException( ServerError.InsufficientAddressCapacity, + "Not enough available addresses to satisfy your minimum request"); + } else { + throw new EC2ServiceException( ServerError.InternalError, "There is insufficient capacity"); + } + } else if (errorCode == 401) { + if ( errorMessage.contains("Unauthorized") ) { + throw new EC2ServiceException(ClientError.AuthFailure, "User not authorised"); + } else { + throw new EC2ServiceException(ClientError.AuthFailure, "User not authorised"); + } + } else { + throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occured"); + } + } else { + if ( errorMessage.contains("Unknown zoneName value") ) { + throw new EC2ServiceException( ClientError.InvalidZone_NotFound, + "AvailabilityZone name is invalid"); + } else if ( errorMessage.contains("No ServiceOffering found to be defined by name") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, "Specified InstanceType is invalid"); + } else if ( errorMessage.contains("Specified Ip permission is invalid") ) { + throw new EC2ServiceException(ClientError.InvalidPermission_Malformed, "Specified Ip permission is invalid"); + } else if ( errorMessage.contains("One or more instanceIds do not exist, other instances rebooted") ) { + throw new EC2ServiceException(ClientError.InvalidInstanceID_NotFound, + "One or more InstanceId doesn't exist, other instances rebooted"); + } else if ( errorMessage.contains("Device is not supported") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, + "Value specified for parameter Device is invalid"); + } else if ( errorMessage.contains("Volume is not attached to the Instance") ) { + throw new EC2ServiceException(ClientError.InvalidAttachment_NotFound, + "Specified Volume is not attached to the specified Instance"); + } else if ( errorMessage.contains("Volume is not attached to the Device") ) { + throw new EC2ServiceException(ClientError.InvalidAttachment_NotFound, + "Specified Volume is not attached to the specified device"); + } else if ( errorMessage.contains("Unable to create snapshot") ) { + throw new EC2ServiceException(ServerError.InternalError, + "Unable to create snapshot"); + } else if ( errorMessage.contains("Instance must be in stopped state") ) { + throw new EC2ServiceException(ClientError.IncorrectInstanceState, + "Specified instance is not in the correct state 'stopped'"); + } else if ( errorMessage.contains("Image couldn't be created") ) { + throw new EC2ServiceException(ServerError.InternalError, + "Unable to create image"); + } else if ( errorMessage.contains("Failed to start the stopped instance") ) { + throw new EC2ServiceException(ServerError.InternalError, + "Unable to start the instance that was stopped during image creation"); + } else if ( errorMessage.contains("One or more of instanceIds specified is in stopped state") ) { + throw new EC2ServiceException(ClientError.IncorrectInstanceState, + "Unable to reboot. One or more of the specified instances is in an incorrect state 'stopped'"); + } else if ( errorMessage.contains("Specified ipAddress doesn't exist") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, "Specified publicIp doesn't exist"); + } else if ( errorMessage.contains("Min Count is greater than the number of instances left to allocate") ) { + throw new EC2ServiceException(ClientError.InstanceLimitExceeded, + "Specified MinCount parameter is greater than the number of instances you can create"); + } else if ( errorMessage.contains("instanceType not found") ) { + throw new EC2ServiceException(ClientError.InvalidParameterValue, + "Specified instanceType not found"); + } else if ( errorMessage.contains("zone not found") ) { + throw new EC2ServiceException(ClientError.InvalidZone_NotFound, + "Specified zone doesn't exist"); + } else if ( errorMessage.contains("Both groupId and groupName has been specified") ) { + throw new EC2ServiceException(ClientError.InvalidParameterCombination, + " for EC2 groups either a group ID or a group name is accepted"); + } else if ( errorMessage.contains("Insufficient Instance Capacity") ) { + throw new EC2ServiceException(ServerError.InsufficientInstanceCapacity, "Insufficient Instance Capacity" ); + } else if ( errorMessage.contains("Unable to find security group name") ) { + throw new EC2ServiceException(ClientError.InvalidGroup_NotFound, "Specified Security Group does not exist" ); + } else if ( errorMessage.contains("Instance not found") ) { + throw new EC2ServiceException(ClientError.InvalidInstanceID_NotFound, + "One or more of the specified instanceId not found"); + } else if ( errorMessage.contains("Cannot modify, instance should be in stopped state") ) { + throw new EC2ServiceException(ClientError.IncorrectInstanceState, + "Unable to modify instance attribute. Specified instance is not in the correct state 'stopped'"); + } else { + throw new EC2ServiceException( ServerError.InternalError, "An unexpected error occured"); + } + } + } } diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2GroupFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2GroupFilterSet.java index dbc367c109d..bd79041518e 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2GroupFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2GroupFilterSet.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; public class EC2GroupFilterSet { @@ -52,11 +53,9 @@ public class EC2GroupFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + if ( value == null || value.equalsIgnoreCase("null")) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ImageFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ImageFilterSet.java index aea3df05dea..646d20f56c4 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ImageFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ImageFilterSet.java @@ -25,6 +25,7 @@ import java.util.Map; import org.apache.log4j.Logger; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; public class EC2ImageFilterSet { protected final static Logger logger = Logger.getLogger(EC2ImageFilterSet.class); @@ -51,10 +52,9 @@ public class EC2ImageFilterSet { String filterName = param.getName(); if ( !filterName.startsWith("tag:") ) { String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + if ( value == null || value.equalsIgnoreCase("null")) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } } filterSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java index b5b7c7840df..a71d476438f 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2InstanceFilterSet.java @@ -24,6 +24,7 @@ import java.util.Map; import com.cloud.bridge.service.EC2SoapServiceImpl; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; public class EC2InstanceFilterSet { @@ -59,11 +60,10 @@ public class EC2InstanceFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "]", 501 ); // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); } diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2KeyPairFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2KeyPairFilterSet.java index 2ad005b7dc2..d27972d5eda 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2KeyPairFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2KeyPairFilterSet.java @@ -25,6 +25,9 @@ import java.util.Map; import org.apache.log4j.Logger; +import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; + public class EC2KeyPairFilterSet { protected final static Logger logger = Logger.getLogger(EC2KeyPairFilterSet.class); @@ -42,16 +45,9 @@ public class EC2KeyPairFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) { - // Changing this to silently ignore - logger.error("Unsupported filter [" + filterName + "] - 1"); - return; - } - - if (null != value && value.equalsIgnoreCase( "null" )) { - logger.error("Unsupported filter [" + filterName + "] - 2"); - return; - } + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ModifyInstanceAttribute.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ModifyInstanceAttribute.java new file mode 100644 index 00000000000..8394e335310 --- /dev/null +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2ModifyInstanceAttribute.java @@ -0,0 +1,64 @@ +// 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 com.cloud.bridge.service.core.ec2; + + +public class EC2ModifyInstanceAttribute { + private String instanceId; + private String instanceType; + private String userData; + + /** + * @return instanceId + */ + public String getInstanceId() { + return instanceId; + } + + /** + * @param instanceId to set + */ + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + /** + * @return instanceType + */ + public String getInstanceType() { + return instanceType; + } + + /** + * @param instanceType to set + */ + public void setInstanceType(String instanceType) { + this.instanceType = instanceType; + } + + /** + * @return userData + */ + public String getUserData() { + return userData; + } + + public void setUserData(String userData) { + this.userData = userData; + } + +} diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2RegisterImage.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2RegisterImage.java index d71329701ea..43b27df6c05 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2RegisterImage.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2RegisterImage.java @@ -72,7 +72,7 @@ public class EC2RegisterImage { if (null != param) { if (!param.contains(":") || param.split(":").length < 4) { throw new EC2ServiceException( ClientError.InvalidParameterValue, "Supported format for " + - "'architecture' is format:zonename:ostypename:hypervisor" ); + "parameter 'architecture' is format:zonename:ostypename:hypervisor" ); } String parts[] = param.split( ":" ); format = parts[0]; @@ -80,9 +80,6 @@ public class EC2RegisterImage { osTypeName = parts[2]; hypervisor = parts[3]; } - else { - throw new EC2ServiceException(ClientError.Unsupported, "Missing Parameter -" + " architecture"); - } } public String getFormat() { diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java index c2bed3ce161..ef395d9818e 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2SnapshotFilterSet.java @@ -27,6 +27,7 @@ import java.util.TimeZone; import com.cloud.bridge.service.UserContext; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; import com.cloud.bridge.util.DateHelper; import com.cloud.bridge.util.EC2RestAuth; @@ -56,12 +57,9 @@ public class EC2SnapshotFilterSet { String filterName = param.getName(); if (!filterName.startsWith("tag:")) { String value = (String) filterTypes.get( filterName ); - - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java index c2d33c39ea1..06edc3870ef 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2TagsFilterSet.java @@ -26,6 +26,7 @@ import java.util.Map; import org.apache.log4j.Logger; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; public class EC2TagsFilterSet { protected final static Logger logger = Logger.getLogger(EC2TagsFilterSet.class); @@ -45,11 +46,9 @@ public class EC2TagsFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } filterSet.add( param ); } diff --git a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java index b8021f3d4ba..af132421474 100644 --- a/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java +++ b/awsapi/src/com/cloud/bridge/service/core/ec2/EC2VolumeFilterSet.java @@ -26,6 +26,7 @@ import java.util.TimeZone; import java.util.Date; import com.cloud.bridge.service.exception.EC2ServiceException; +import com.cloud.bridge.service.exception.EC2ServiceException.ClientError; import com.cloud.bridge.util.EC2RestAuth; @@ -61,11 +62,9 @@ public class EC2VolumeFilterSet { String filterName = param.getName(); String value = (String) filterTypes.get( filterName ); - if (null == value) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 1", 501 ); - - if (null != value && value.equalsIgnoreCase( "null" )) - throw new EC2ServiceException( "Unsupported filter [" + filterName + "] - 2", 501 ); + if ( value == null || value.equalsIgnoreCase("null") ) { + throw new EC2ServiceException( ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid"); + } // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer) filterSet.add( param ); } diff --git a/awsapi/src/com/cloud/bridge/service/exception/EC2ServiceException.java b/awsapi/src/com/cloud/bridge/service/exception/EC2ServiceException.java index e1f515ad2c0..c21e6e9574f 100644 --- a/awsapi/src/com/cloud/bridge/service/exception/EC2ServiceException.java +++ b/awsapi/src/com/cloud/bridge/service/exception/EC2ServiceException.java @@ -26,11 +26,11 @@ public class EC2ServiceException extends RuntimeException { // ServerError & ClientError are correct as of schema version 2010-08-31 public static enum ServerError { - InsufficientAddressCapacity("Server.InsufficientAddressCapacity", 500), - InsufficientInstanceCapacity("Server.InsufficientInstanceCapacity", 500), - InsufficientReservedInstanceCapacity("Server.InsufficientReservedInstanceCapacity", 500), - InternalError("Server.InternalError", 500), - Unavailable("Server.Unavailable", 501); + InsufficientAddressCapacity("Server.InsufficientAddressCapacity", 500), + InsufficientInstanceCapacity("Server.InsufficientInstanceCapacity", 500), + InsufficientReservedInstanceCapacity("Server.InsufficientReservedInstanceCapacity", 500), + InternalError("Server.InternalError", 500), + Unavailable("Server.Unavailable", 501); private String errorString; private int httpErrorCode; @@ -45,58 +45,64 @@ public class EC2ServiceException extends RuntimeException { } public static enum ClientError { - AddressLimitExceeded("Client.AddressLimitExceeded", 400), - AttachmentLimitExceeded("Client.AttachmentLimitExceeded", 400), - AuthFailure("Client.AuthFailure", 400), - Blocked("Client.Blocked", 400), - FilterLimitExceeded("Client.FilterLimitExceeded", 400), - IdempotentParameterMismatch("Client.IdempotentParameterMismatch", 400), - IncorrectState("Client.IncorrectState", 400), - InstanceLimitExceeded("Client.InstanceLimitExceeded", 400), - InsufficientInstanceCapacity("Client.InsufficientInstanceCapacity", 400), - InsufficientReservedInstancesCapacity("Client.InsufficientReservedInstancesCapacity", 400), - InvalidAMIAttributeItemValue("Client.InvalidAMIAttributeItemValue", 400), - InvalidAMIID_Malformed("Client.InvalidAMIID.Malformed", 400), - InvalidAMIID_NotFound("Client.InvalidAMIID.NotFound", 400), - InvalidAMIID_Unavailable("Client.InvalidAMIID.Unavailable", 400), - InvalidAttachment_NotFound("Client.InvalidAttachment.NotFound", 400), - InvalidDevice_InUse("Client.InvalidDevice.InUse", 400), - InvalidGroup_Duplicate("Client.InvalidGroup.Duplicate", 400), - InvalidGroup_InUse("Client.InvalidGroup.InUse", 400), - InvalidGroup_NotFound("Client.InvalidGroup.NotFound", 400), - InvalidGroup_Reserved("Client.InvalidGroup.Reserved", 400), - InvalidInstanceID_Malformed("Client.InvalidInstanceID.Malformed", 400), - InvalidInstanceID_NotFound("Client.InvalidInstanceID.NotFound", 400), - InvalidIPAddress_InUse("Client.InvalidIPAddress.InUse", 400), - InvalidKeyPair_Duplicate("Client.InvalidKeyPair.Duplicate", 400), - InvalidKeyPair_Format("Client.InvalidKeyPair.Format", 400), - InvalidKeyPair_NotFound("Client.InvalidKeyPair.NotFound", 400), - InvalidManifest("Client.InvalidManifest", 400), - InvalidParameterCombination("Client.InvalidParameterCombination", 400), - InvalidParameterValue("Client.InvalidParameterValue", 400), - InvalidPermission_Duplicate("Client.InvalidPermission.Duplicate", 400), - InvalidPermission_Malformed("Client.InvalidPermission.Malformed", 400), - InvalidReservationID_Malformed("Client.InvalidReservationID.Malformed", 400), - InvalidReservationID_NotFound("Client.InvalidReservationID.NotFound", 400), - InvalidResourceId_Format("Client.InvalidResourceId.Format", 400), - InvalidSnapshotID_Malformed("Client.InvalidSnapshotID.Malformed", 400), - InvalidSnapshot_NotFound("Client.InvalidSnapshot.NotFound", 400), - InvalidUserID_Malformed("Client.InvalidUserID.Malformed", 400), - InvalidReservedInstancesId("Client.InvalidReservedInstancesId", 400), - InvalidReservedInstancesOfferingId("Client.InvalidReservedInstancesOfferingId", 400), - InvalidVolumeID_Duplicate("Client.InvalidVolumeID.Duplicate", 400), - InvalidVolumeID_Malformed("Client.InvalidVolumeID.Malformed", 400), - InvalidVolume_NotFound("Client.InvalidVolume.NotFound", 400), - InvalidVolumeID_ZoneMismatch("Client.InvalidVolumeID.ZoneMismatch", 400), - InvalidZone_NotFound("Client.InvalidZone.NotFound", 400), - NonEBSInstance("Client.NonEBSInstance", 400), - PendingVerification("Client.PendingVerification", 400), - PendingSnapshotLimitExceeded("Client.PendingSnapshotLimitExceeded", 400), - ReservedInstancesLimitExceeded("Client.ReservedInstancesLimitExceeded", 400), - SnapshotLimitExceeded("Client.SnapshotLimitExceeded", 400), - UnknownParameter("Client.UnknownParameter", 400), - Unsupported("Client.Unsupported", 400), - VolumeLimitExceeded("Client.VolumeLimitExceeded", 400); + AddressLimitExceeded("Client.AddressLimitExceeded", 400), + AttachmentLimitExceeded("Client.AttachmentLimitExceeded", 400), + AuthFailure("Client.AuthFailure", 400), + Blocked("Client.Blocked", 400), + DependencyViolation("Client.DependencyViolation", 400), + FilterLimitExceeded("Client.FilterLimitExceeded", 400), + IdempotentParameterMismatch("Client.IdempotentParameterMismatch", 400), + IncorrectState("Client.IncorrectState", 400), + IncorrectInstanceState("Client.IncorrectInstanceState", 400), + InstanceLimitExceeded("Client.InstanceLimitExceeded", 400), + InsufficientInstanceCapacity("Client.InsufficientInstanceCapacity", 400), + InsufficientReservedInstancesCapacity("Client.InsufficientReservedInstancesCapacity", 400), + InvalidAMIAttributeItemValue("Client.InvalidAMIAttributeItemValue", 400), + InvalidAMIID_Malformed("Client.InvalidAMIID.Malformed", 400), + InvalidAMIID_NotFound("Client.InvalidAMIID.NotFound", 400), + InvalidAMIID_Unavailable("Client.InvalidAMIID.Unavailable", 400), + InvalidAttachment_NotFound("Client.InvalidAttachment.NotFound", 400), + InvalidDevice_InUse("Client.InvalidDevice.InUse", 400), + InvalidFilter("Client.InvalidFilter", 400), + InvalidGroup_Duplicate("Client.InvalidGroup.Duplicate", 400), + InvalidGroup_InUse("Client.InvalidGroup.InUse", 400), + InvalidGroup_NotFound("Client.InvalidGroup.NotFound", 400), + InvalidGroup_Reserved("Client.InvalidGroup.Reserved", 400), + InvalidInstanceID_Malformed("Client.InvalidInstanceID.Malformed", 400), + InvalidInstanceID_NotFound("Client.InvalidInstanceID.NotFound", 400), + InvalidIPAddress_InUse("Client.InvalidIPAddress.InUse", 400), + InvalidKeyPair_Duplicate("Client.InvalidKeyPair.Duplicate", 400), + InvalidKeyPair_Format("Client.InvalidKeyPair.Format", 400), + InvalidKeyPair_NotFound("Client.InvalidKeyPair.NotFound", 400), + InvalidManifest("Client.InvalidManifest", 400), + InvalidParameterCombination("Client.InvalidParameterCombination", 400), + InvalidParameterValue("Client.InvalidParameterValue", 400), + InvalidPermission_Duplicate("Client.InvalidPermission.Duplicate", 400), + InvalidPermission_Malformed("Client.InvalidPermission.Malformed", 400), + InvalidReservationID_Malformed("Client.InvalidReservationID.Malformed", 400), + InvalidReservationID_NotFound("Client.InvalidReservationID.NotFound", 400), + InvalidSecurity_RequestHasExpired("Client.InvalidSecurity.RequestHasExpired", 400), + InvalidSnapshotID_Malformed("Client.InvalidSnapshotID.Malformed", 400), + InvalidSnapshot_NotFound("Client.InvalidSnapshot.NotFound", 400), + InvalidUserID_Malformed("Client.InvalidUserID.Malformed", 400), + InvalidReservedInstancesId("Client.InvalidReservedInstancesId", 400), + InvalidReservedInstancesOfferingId("Client.InvalidReservedInstancesOfferingId", 400), + InvalidVolumeID_Duplicate("Client.InvalidVolumeID.Duplicate", 400), + InvalidVolumeID_Malformed("Client.InvalidVolumeID.Malformed", 400), + InvalidVolume_NotFound("Client.InvalidVolume.NotFound", 400), + InvalidVolumeID_ZoneMismatch("Client.InvalidVolumeID.ZoneMismatch", 400), + InvalidZone_NotFound("Client.InvalidZone.NotFound", 400), + MissingParamter("Client.MissingParamter", 400), + NonEBSInstance("Client.NonEBSInstance", 400), + PendingVerification("Client.PendingVerification", 400), + PendingSnapshotLimitExceeded("Client.PendingSnapshotLimitExceeded", 400), + SignatureDoesNotMatch("Client.SignatureDoesNotMatch", 400), + ReservedInstancesLimitExceeded("Client.ReservedInstancesLimitExceeded", 400), + ResourceLimitExceeded("Client.ResourceLimitExceeded", 400), + SnapshotLimitExceeded("Client.SnapshotLimitExceeded", 400), + UnknownParameter("Client.UnknownParameter", 400), + Unsupported("Client.UnsupportedOperation", 400), + VolumeLimitExceeded("Client.VolumeLimitExceeded", 400); private String errorString; private int httpErrorCode; diff --git a/awsapi/src/com/cloud/stack/CloudStackClient.java b/awsapi/src/com/cloud/stack/CloudStackClient.java index 5017bd423dd..fa114f5a2cf 100644 --- a/awsapi/src/com/cloud/stack/CloudStackClient.java +++ b/awsapi/src/com/cloud/stack/CloudStackClient.java @@ -103,8 +103,8 @@ public class CloudStackClient { int jobStatus = queryAsyncJobResponse.getAsInt("queryasyncjobresultresponse.jobstatus"); switch(jobStatus) { case 2: - throw new Exception(queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errorcode") + " " + - queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errortext")); + throw new Exception(queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errortext") + " Error Code - " + + queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errorcode") ); case 0 : try { @@ -179,6 +179,7 @@ public class CloudStackClient { if(errorMessage == null){ errorMessage = "CloudStack API call HTTP response error, HTTP status code: " + statusCode; } + errorMessage = errorMessage.concat(" Error Code - " + Integer.toString(statusCode)); throw new IOException(errorMessage); }