# 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. """Exceptions for use in the Placement API.""" from oslo_log import log as logging LOG = logging.getLogger(__name__) class _BaseException(Exception): """Base 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." def __init__(self, message=None, **kwargs): self.kwargs = kwargs if not message: try: message = self.msg_fmt % kwargs except Exception: # NOTE(melwitt): This is done in a separate method so it can be # monkey-patched during testing to make it a hard failure. self._log_exception() message = self.msg_fmt self.message = message super(_BaseException, self).__init__(message) def _log_exception(self): # 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 self.kwargs.items(): LOG.error("%s: %s" % (name, value)) # noqa def format_message(self): # Use the first argument to the python Exception object which # should be our full exception message, (see __init__). return self.args[0] class NotFound(_BaseException): msg_fmt = "Resource could not be found." class Exists(_BaseException): msg_fmt = "Resource already exists." class InvalidInventory(_BaseException): msg_fmt = ("Inventory for '%(resource_class)s' on " "resource provider '%(resource_provider)s' invalid.") class CannotDeleteParentResourceProvider(_BaseException): msg_fmt = ("Cannot delete resource provider that is a parent of " "another. Delete child providers first.") class ConcurrentUpdateDetected(_BaseException): msg_fmt = ("Another thread concurrently updated the data. " "Please retry your update") class ResourceProviderConcurrentUpdateDetected(ConcurrentUpdateDetected): msg_fmt = ("Another thread concurrently updated the resource provider " "data. Please retry your update") class ResourceProviderNotFound(NotFound): # Marker exception indicating that we've filtered down to zero possible # allocation candidates. Does not represent an API error; should only be # used internally: no results is a 200 with empty allocation_requests. msg_fmt = "No results are possible." class InvalidAllocationCapacityExceeded(InvalidInventory): msg_fmt = ("Unable to create allocation for '%(resource_class)s' on " "resource provider '%(resource_provider)s'. The requested " "amount would exceed the capacity.") class InvalidAllocationConstraintsViolated(InvalidInventory): msg_fmt = ("Unable to create allocation for '%(resource_class)s' on " "resource provider '%(resource_provider)s'. The requested " "amount would violate inventory constraints.") class InvalidInventoryCapacity(InvalidInventory): msg_fmt = ("Invalid inventory for '%(resource_class)s' on " "resource provider '%(resource_provider)s'. " "The reserved value is greater than or equal to total.") class InvalidInventoryCapacityReservedCanBeTotal(InvalidInventoryCapacity): msg_fmt = ("Invalid inventory for '%(resource_class)s' on " "resource provider '%(resource_provider)s'. " "The reserved value is greater than total.") # An exception with this name is used on both sides of the placement/ # nova interaction. class InventoryInUse(InvalidInventory): msg_fmt = ("Inventory for '%(resource_classes)s' on " "resource provider '%(resource_provider)s' in use.") class InventoryWithResourceClassNotFound(NotFound): msg_fmt = "No inventory of class %(resource_class)s found." class MaxDBRetriesExceeded(_BaseException): msg_fmt = ("Max retries of DB transaction exceeded attempting to " "perform %(action)s.") class ObjectActionError(_BaseException): msg_fmt = 'Object action %(action)s failed because: %(reason)s' class PolicyNotAuthorized(_BaseException): msg_fmt = "Policy does not allow %(action)s to be performed." class ResourceClassCannotDeleteStandard(_BaseException): msg_fmt = "Cannot delete standard resource class %(resource_class)s." class ResourceClassCannotUpdateStandard(_BaseException): msg_fmt = "Cannot update standard resource class %(resource_class)s." class ResourceClassExists(_BaseException): msg_fmt = "Resource class %(resource_class)s already exists." class ResourceClassInUse(_BaseException): msg_fmt = ("Cannot delete resource class %(resource_class)s. " "Class is in use in inventory.") class ResourceClassNotFound(NotFound): msg_fmt = "No such resource class %(name)s." class ResourceProviderInUse(_BaseException): msg_fmt = "Resource provider has allocations." class TraitCannotDeleteStandard(_BaseException): msg_fmt = "Cannot delete standard trait %(name)s." class TraitExists(_BaseException): msg_fmt = "The Trait %(name)s already exists" class TraitInUse(_BaseException): msg_fmt = "The trait %(name)s is in use by a resource provider." class TraitNotFound(NotFound): msg_fmt = "No such trait(s): %(name)s." class ProjectNotFound(NotFound): msg_fmt = "No such project(s): %(external_id)s." class ProjectExists(Exists): msg_fmt = "The project %(external_id)s already exists." class UserNotFound(NotFound): msg_fmt = "No such user(s): %(external_id)s." class UserExists(Exists): msg_fmt = "The user %(external_id)s already exists." class ConsumerNotFound(NotFound): msg_fmt = "No such consumer(s): %(uuid)s." class ConsumerExists(Exists): msg_fmt = "The consumer %(uuid)s already exists."