ec2-api/ec2api/exception.py

381 lines
10 KiB
Python

# Copyright 2014
# The Cloudscaling Group, Inc.
#
# Licensed 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.
"""ec2api base exception handling.
Includes decorator for re-raising ec2api-type exceptions.
SHOULD include dedicated exception logging.
"""
import sys
from oslo.config import cfg
from ec2api.openstack.common.gettextutils import _
from ec2api.openstack.common import log as logging
LOG = logging.getLogger(__name__)
exc_log_opts = [
cfg.BoolOpt('fatal_exception_format_errors',
default=False,
help='Make exception message format errors fatal'),
]
CONF = cfg.CONF
CONF.register_opts(exc_log_opts)
class EC2ServerError(Exception):
def __init__(self, response, content):
self.response = response
self.content = content
class EC2Exception(Exception):
"""Base EC2 Exception
To correctly use this class, inherit from it and define
a 'msg_fmt' property. That msg_fmt will get printf'd
with the keyword arguments provided to the constructor.
"""
msg_fmt = _("An unknown exception occurred.")
code = 500
headers = {}
safe = False
def __init__(self, message=None, **kwargs):
self.kwargs = kwargs
if 'code' not in self.kwargs:
try:
self.kwargs['code'] = self.code
except AttributeError:
pass
if not message:
try:
message = self.msg_fmt % kwargs
except Exception:
exc_info = sys.exc_info()
# kwargs doesn't match a variable in the message
# log the issue and the kwargs
LOG.exception(_('Exception in string format operation'))
for name, value in kwargs.iteritems():
LOG.error("%s: %s" % (name, value))
if CONF.fatal_exception_format_errors:
raise exc_info[0], exc_info[1], exc_info[2]
else:
# at least get the core message out if something happened
message = self.msg_fmt
super(EC2Exception, self).__init__(message)
def format_message(self):
# NOTE(mrodden): use the first argument to the python Exception object
# which should be our full EC2Exception message, (see __init__)
return self.args[0]
class Unsupported(EC2Exception):
msg_fmt = _("The specified request is unsupported. %(reason)s")
code = 400
class Overlimit(EC2Exception):
msg_fmt = _("Limit exceeded.")
code = 400
class Invalid(EC2Exception):
msg_fmt = _("Unacceptable parameters.")
code = 400
class InvalidRequest(Invalid):
msg_fmt = _("The request is invalid.")
class InvalidAttribute(Invalid):
msg_fmt = _("Attribute not supported: %(attr)s")
class InvalidId(Invalid):
msg_fmt = _("The ID '%(id)s' is not valid")
class InvalidInput(Invalid):
msg_fmt = _("Invalid input received: %(reason)s")
class ConfigNotFound(EC2Exception):
msg_fmt = _("Could not find config at %(path)s")
class PasteAppNotFound(EC2Exception):
msg_fmt = _("Could not load paste app '%(name)s' from %(path)s")
class Forbidden(EC2Exception):
ec2_code = 'AuthFailure'
msg_fmt = _("Not authorized.")
code = 403
class AuthFailure(Invalid):
pass
class NotFound(EC2Exception):
msg_fmt = _("Resource could not be found.")
code = 404
class ValidationError(Invalid):
msg_fmt = _("The input fails to satisfy the constraints "
"specified by an AWS service: '%(reason)s'")
class EC2NotFound(NotFound):
code = 400
class NovaDbImageNotFound(EC2NotFound):
ec2_code = 'InvalidAMIID.NotFound'
msg_fmt = _("The image id '[%(image_id)s]' does not exist")
class NovaDbInstanceNotFound(EC2NotFound):
ec2_code = 'InvalidInstanceID.NotFound'
msg_fmt = _("Instance %(instance_id)s could not be found.")
class InvalidInstanceIDNotFound(EC2NotFound):
ec2_code = 'InvalidInstanceID.NotFound'
msg_fmt = _("The instance ID '%(id)s' does not exist")
class InvalidVpcIDNotFound(EC2NotFound):
ec2_code = 'InvalidVpcID.NotFound'
msg_fmt = _("The vpc ID '%(id)s' does not exist")
class InvalidInternetGatewayIDNotFound(EC2NotFound):
ec2_code = 'InvalidInternetGatewayID.NotFound'
msg_fmt = _("The internetGateway ID '%(id)s' does not exist")
class InvalidSubnetIDNotFound(EC2NotFound):
ec2_code = 'InvalidSubnetID.NotFound'
msg_fmt = _("The subnet ID '%(id)s' does not exist")
class InvalidNetworkInterfaceIDNotFound(EC2NotFound):
ec2_code = 'InvalidNetworkInterfaceID.NotFound'
msg_fmt = _("Network interface %(id)s could not "
"be found.")
class InvalidAttachmentIDNotFound(EC2NotFound):
ec2_code = 'InvalidAttachmentID.NotFound'
msg_fmt = _("Attachment %(id)s could not "
"be found.")
class InvalidDhcpOptionsIDNotFound(EC2NotFound):
ec2_code = 'InvalidDhcpOptionsID.NotFound'
msg_fmt = _("The dhcp options ID '%(id)s' does not exist")
class InvalidAllocationIDNotFound(EC2NotFound):
ec2_code = 'InvalidAllocationID.NotFound'
msg_fmt = _("The allocation ID '%(id)s' does not exist")
class InvalidAssociationIDNotFound(EC2NotFound):
ec2_code = 'InvalidAssociationID.NotFound'
msg_fmt = _("The association ID '%(id)s' does not exist")
class InvalidRouteTableIDNotFound(EC2NotFound):
ec2_code = 'InvalidRouteTableID.NotFound'
msg_fmt = _("The routeTable ID '%(id)s' does not exist")
class InvalidRouteNotFound(EC2NotFound):
ec2_code = 'InvalidRoute.NotFound'
msg_fmt = _('No route with destination-cidr-block '
'%(destination_cidr_block)s in route table %(route_table_id)s')
class InvalidSecurityGroupIDNotFound(EC2NotFound):
ec2_code = 'InvalidSecurityGroupID.NotFound'
msg_fmt = _("The securityGroup ID '%(id)s' does not exist")
class InvalidGroupNotFound(EC2NotFound):
ec2_code = 'InvalidGroup.NotFound'
msg_fmg = _("The security group ID '%(id)s' does not exist")
class InvalidPermissionNotFound(EC2NotFound):
ec2_code = 'InvalidPermission.NotFound'
msg_fmg = _("The specified permission does not exist")
class InvalidVolumeNotFound(EC2NotFound):
ec2_code = 'InvalidVolume.NotFound'
msg_fmt = _("The volume '%(id)s' does not exist.")
class InvalidSnapshotNotFound(EC2NotFound):
ec2_code = 'InvalidSnapshot.NotFound'
msg_fmt = _("Snapshot %(id)s could not be found.")
class InvalidAMIIDNotFound(EC2NotFound):
ec2_code = 'InvalidAMIID.NotFound'
msg_fmt = _("The image id '[%(id)s]' does not exist")
class IncorrectState(EC2Exception):
ec2_code = 'IncorrectState'
code = 400
msg_fmt = _("The resource is in incorrect state for the request - reason: "
"'%(reason)s'")
class InvalidVpcRange(Invalid):
ec2_code = 'InvalidVpc.Range'
msg_fmt = _("The CIDR '%(cidr_block)s' is invalid.")
class InvalidSubnetRange(Invalid):
ec2_code = 'InvalidSubnet.Range'
msg_fmt = _("The CIDR '%(cidr_block)s' is invalid.")
class InvalidSubnetConflict(Invalid):
ec2_code = 'InvalidSubnet.Conflict'
msg_fmt = _("The CIDR '%(cidr_block)s' conflicts with another subnet")
class MissingParameter(Invalid):
msg_fmt = _("The required parameter '%(param)s' is missing")
class InvalidParameterValue(Invalid):
msg_fmt = _("Value (%(value)s) for parameter %(parameter)s is invalid. "
"%(reason)s")
class InvalidParameterCombination(Invalid):
pass
class ResourceAlreadyAssociated(Invalid):
ec2_code = 'Resource.AlreadyAssociated'
class GatewayNotAttached(Invalid):
ec2_code = 'Gateway.NotAttached'
msg_fmt = _("resource %(igw_id)s is not attached to network %(vpc_id)s")
class DependencyViolation(Invalid):
msg_fmt = _('Object %(obj1_id)s has dependent resource %(obj2_id)s')
class InvalidNetworkInterfaceInUse(Invalid):
ec2_code = 'InvalidNetworkInterface.InUse'
msg_fmt = _('Interface: %(interface_ids)s in use.')
class InvalidInstanceId(Invalid):
ec2_code = 'InvalidInstanceID'
msg_fmt = _("There are multiple interfaces attached to instance "
"'%(instance_id)s'. Please specify an interface ID for "
"the operation instead.")
class InvalidIPAddressInUse(Invalid):
ec2_code = 'InvalidIPAddress.InUse'
msg_fmt = _('Address %(ip_address)s is in use.')
class InvalidAddressNotFound(Invalid):
ec2_code = 'InvalidAddress.NotFound'
msg_fmt = _('The specified elastic IP address %(ip)s cannot be found.')
class RouteAlreadyExists(Invalid):
msg_fmt = _('The route identified by %(destination_cidr_block)s '
'already exists.')
class NetworkInterfaceLimitExceeded(Overlimit):
msg_fmt = _('You have reached the limit of network interfaces for subnet'
'%(subnet_id)s.')
class ResourceLimitExceeded(Overlimit):
msg_fmt = _('You have reached the limit of %(resource)s')
class SecurityGroupLimitExceeded(Overlimit):
msg_fmt = _('You have reached the limit of security groups')
class ImageNotActive(Invalid):
ec2_code = 'InvalidAMIID.Unavailable'
# TODO(ft): Change the message with the real AWS message
msg_fmt = _("Image %(image_id)s is not active.")
class InvalidSnapshotIDMalformed(Invalid):
ec2_code = 'InvalidSnapshotID.Malformed'
# TODO(ft): Change the message with the real AWS message
msg_fmg = _('The snapshot %(id)s ID is not valid')
class InvalidKeypairNotFound(NotFound):
ec2_code = 'InvalidKeyPair.NotFound'
msg_fmt = _("Keypair %(id)s is not found")
class InvalidAvailabilityZoneNotFound(NotFound):
ec2_code = 'InvalidAvailabilityZone.NotFound'
msg_fmt = _("Availability zone %(id)s not found")
class InvalidKeyPairDuplicate(Invalid):
ec2_code = 'InvalidKeyPair.Duplicate'
msg_fmt = _("Key pair '%(key_name)s' already exists.")
class InvalidPermissionDuplicate(Invalid):
ec2_code = 'InvalidPermission.Duplicate'
msg_fmt = _("The specified rule already exists for that security group.")
class RulesPerSecurityGroupLimitExceeded(Overlimit):
msg_fmt = _("You've reached the limit on the number of rules that "
"you can add to a security group.")