Move placement exceptions into the placement package
This change moves the exceptions raised within the placement service into the nova.api.openstack.placement package. This is part of the process of unifying all placement code into one subdirectory so that a future lift and shift is easier and cleaner. This is mostly a straightforward change of imports and a moving of existing exceptions in the placements handlers and objects with a few caveats: * Dealing with nova/db/sqlalchemy/resource_class_cache.py has not yet been accomplished, so it remains where it is and imports exceptions from the placement hierarchy. A TODO indicating some of the options is left for future work. * Exceptions with the name ResourceProviderInUse and InventoryInUse are used on both sides of the nova/placement interaction. This is noted with comments in both nova/exception.py and placement/exception.py. * test_report_client.py has had a TODO added to make it clear that the exceptions it uses are nova-side, and perhaps the test file should be moved. * The base class of the original exceptions, NoveException, does a bit more than is required on the placement side so a new private class _BaseException is created which removes support for handling 'code'. This is not required because all exceptions in placement are supposed to be manually caught in handlers and explicitly transformed into http exceptions. blueprint placement-extract Change-Id: I2b94945a0963d6a61af931505b69afe2d4733759
This commit is contained in:
parent
37b4f77b5e
commit
1a072eab33
|
@ -0,0 +1,167 @@
|
|||
# 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."""
|
||||
|
||||
# NOTE(cdent): The exceptions are copied from nova.exception, where they
|
||||
# were originally used. To prepare for extracting placement to its own
|
||||
# repository we wish to no longer do that. Instead, exceptions used by
|
||||
# placement should be in the placement hierarchy.
|
||||
# TODO(cdent): Because of the duplication it is likely that some of the
|
||||
# functionality provided by _BaseException is redundant and can be factored
|
||||
# out.
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from nova.i18n import _, _LE
|
||||
|
||||
|
||||
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(_LE('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 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 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.")
|
||||
|
||||
|
||||
# An exception with this name is used on both sides of the placement/
|
||||
# nova interaction.
|
||||
class InventoryInUse(InvalidInventory):
|
||||
# NOTE(mriedem): This message cannot change without impacting the
|
||||
# nova.scheduler.client.report._RE_INV_IN_USE regex.
|
||||
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 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 %(resource_class)s.")
|
||||
|
||||
|
||||
# An exception with this name is used on both sides of the placement/
|
||||
# nova interaction.
|
||||
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): %(names)s.")
|
|
@ -28,6 +28,7 @@ import webob
|
|||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement.handlers import aggregate
|
||||
from nova.api.openstack.placement.handlers import allocation
|
||||
from nova.api.openstack.placement.handlers import allocation_candidate
|
||||
|
@ -39,7 +40,6 @@ from nova.api.openstack.placement.handlers import trait
|
|||
from nova.api.openstack.placement.handlers import usage
|
||||
from nova.api.openstack.placement import policy
|
||||
from nova.api.openstack.placement import util
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -19,12 +19,12 @@ from oslo_utils import encodeutils
|
|||
from oslo_utils import timeutils
|
||||
import webob
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement import microversion
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova.api.openstack.placement.schemas import allocation as schema
|
||||
from nova.api.openstack.placement import util
|
||||
from nova.api.openstack.placement import wsgi_wrapper
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
|
||||
|
||||
|
|
|
@ -20,12 +20,12 @@ from oslo_utils import timeutils
|
|||
import six
|
||||
import webob
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement import microversion
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova.api.openstack.placement.schemas import allocation_candidate as schema
|
||||
from nova.api.openstack.placement import util
|
||||
from nova.api.openstack.placement import wsgi_wrapper
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
|
||||
|
||||
|
|
|
@ -18,13 +18,13 @@ from oslo_serialization import jsonutils
|
|||
from oslo_utils import encodeutils
|
||||
import webob
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement import microversion
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova.api.openstack.placement.schemas import inventory as schema
|
||||
from nova.api.openstack.placement import util
|
||||
from nova.api.openstack.placement import wsgi_wrapper
|
||||
from nova.db import constants as db_const
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
|
||||
|
||||
|
|
|
@ -16,12 +16,12 @@ from oslo_utils import encodeutils
|
|||
from oslo_utils import timeutils
|
||||
import webob
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement import microversion
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova.api.openstack.placement.schemas import resource_class as schema
|
||||
from nova.api.openstack.placement import util
|
||||
from nova.api.openstack.placement import wsgi_wrapper
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@ from oslo_utils import timeutils
|
|||
from oslo_utils import uuidutils
|
||||
import webob
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement import microversion
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova.api.openstack.placement.schemas import resource_provider as rp_schema
|
||||
from nova.api.openstack.placement import util
|
||||
from nova.api.openstack.placement import wsgi_wrapper
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
|
||||
|
||||
|
|
|
@ -17,12 +17,12 @@ from oslo_utils import encodeutils
|
|||
from oslo_utils import timeutils
|
||||
import webob
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement import microversion
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova.api.openstack.placement.schemas import trait as schema
|
||||
from nova.api.openstack.placement import util
|
||||
from nova.api.openstack.placement import wsgi_wrapper
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
|
||||
|
||||
|
|
|
@ -16,12 +16,12 @@ from oslo_utils import encodeutils
|
|||
from oslo_utils import timeutils
|
||||
import webob
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement import microversion
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova.api.openstack.placement.schemas import usage as schema
|
||||
from nova.api.openstack.placement import util
|
||||
from nova.api.openstack.placement import wsgi_wrapper
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
|
||||
|
||||
|
|
|
@ -36,10 +36,10 @@ from sqlalchemy import func
|
|||
from sqlalchemy import sql
|
||||
from sqlalchemy.sql import null
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.db.sqlalchemy import api as db_api
|
||||
from nova.db.sqlalchemy import api_models as models
|
||||
from nova.db.sqlalchemy import resource_class_cache as rc_cache
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import rc_fields
|
||||
|
||||
|
|
|
@ -14,9 +14,12 @@ from oslo_concurrency import lockutils
|
|||
import six
|
||||
import sqlalchemy as sa
|
||||
|
||||
# TODO(cdent): This file and its location is problematic for placement
|
||||
# extraction but we probably want to switch to os-resource-classes (like
|
||||
# os-traits) instead of moving it?
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.db.sqlalchemy import api as db_api
|
||||
from nova.db.sqlalchemy import api_models as models
|
||||
from nova import exception
|
||||
from nova import rc_fields as fields
|
||||
|
||||
_RC_TBL = models.ResourceClass.__table__
|
||||
|
|
|
@ -2068,11 +2068,6 @@ class LibguestfsCannotReadKernel(Invalid):
|
|||
msg_fmt = _("Libguestfs does not have permission to read host kernel.")
|
||||
|
||||
|
||||
class MaxDBRetriesExceeded(NovaException):
|
||||
msg_fmt = _("Max retries of DB transaction exceeded attempting to "
|
||||
"perform %(action)s.")
|
||||
|
||||
|
||||
class RealtimePolicyNotSupported(Invalid):
|
||||
msg_fmt = _("Realtime policy not supported by hypervisor")
|
||||
|
||||
|
@ -2107,20 +2102,8 @@ class InvalidReservedMemoryPagesOption(Invalid):
|
|||
"config-reference.")
|
||||
|
||||
|
||||
class ConcurrentUpdateDetected(NovaException):
|
||||
msg_fmt = _("Another thread concurrently updated the data. "
|
||||
"Please retry your update")
|
||||
|
||||
|
||||
class ResourceClassNotFound(NotFound):
|
||||
msg_fmt = _("No such resource class %(resource_class)s.")
|
||||
|
||||
|
||||
class CannotDeleteParentResourceProvider(NovaException):
|
||||
msg_fmt = _("Cannot delete resource provider that is a parent of "
|
||||
"another. Delete child providers first.")
|
||||
|
||||
|
||||
# An exception with this name is used on both sides of the placement/
|
||||
# nova interaction.
|
||||
class ResourceProviderInUse(NovaException):
|
||||
msg_fmt = _("Resource provider has allocations.")
|
||||
|
||||
|
@ -2168,31 +2151,10 @@ class ResourceProviderUpdateConflict(PlacementAPIConflict):
|
|||
"provider %(uuid)s (generation %(generation)d): %(error)s")
|
||||
|
||||
|
||||
class InventoryWithResourceClassNotFound(NotFound):
|
||||
msg_fmt = _("No inventory of class %(resource_class)s found.")
|
||||
|
||||
|
||||
class InvalidResourceClass(Invalid):
|
||||
msg_fmt = _("Resource class '%(resource_class)s' invalid.")
|
||||
|
||||
|
||||
class ResourceClassExists(NovaException):
|
||||
msg_fmt = _("Resource class %(resource_class)s already exists.")
|
||||
|
||||
|
||||
class ResourceClassInUse(Invalid):
|
||||
msg_fmt = _("Cannot delete resource class %(resource_class)s. "
|
||||
"Class is in use in inventory.")
|
||||
|
||||
|
||||
class ResourceClassCannotDeleteStandard(Invalid):
|
||||
msg_fmt = _("Cannot delete standard resource class %(resource_class)s.")
|
||||
|
||||
|
||||
class ResourceClassCannotUpdateStandard(Invalid):
|
||||
msg_fmt = _("Cannot update standard resource class %(resource_class)s.")
|
||||
|
||||
|
||||
class InvalidResourceAmount(Invalid):
|
||||
msg_fmt = _("Resource amounts must be integers. Received '%(amount)s'.")
|
||||
|
||||
|
@ -2202,6 +2164,8 @@ class InvalidInventory(Invalid):
|
|||
"resource provider '%(resource_provider)s' invalid.")
|
||||
|
||||
|
||||
# An exception with this name is used on both sides of the placement/
|
||||
# nova interaction.
|
||||
class InventoryInUse(InvalidInventory):
|
||||
# NOTE(mriedem): This message cannot change without impacting the
|
||||
# nova.scheduler.client.report._RE_INV_IN_USE regex.
|
||||
|
@ -2209,24 +2173,6 @@ class InventoryInUse(InvalidInventory):
|
|||
"resource provider '%(resource_provider)s' in use.")
|
||||
|
||||
|
||||
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 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 UnsupportedPointerModelRequested(Invalid):
|
||||
msg_fmt = _("Pointer model '%(model)s' requested is not supported by "
|
||||
"host.")
|
||||
|
@ -2268,22 +2214,6 @@ class PowerVMAPIFailed(NovaException):
|
|||
"%(reason)s")
|
||||
|
||||
|
||||
class TraitNotFound(NotFound):
|
||||
msg_fmt = _("No such trait(s): %(names)s.")
|
||||
|
||||
|
||||
class TraitExists(NovaException):
|
||||
msg_fmt = _("The Trait %(name)s already exists")
|
||||
|
||||
|
||||
class TraitCannotDeleteStandard(Invalid):
|
||||
msg_fmt = _("Cannot delete standard trait %(name)s.")
|
||||
|
||||
|
||||
class TraitInUse(Invalid):
|
||||
msg_fmt = _("The trait %(name)s is in use by a resource provider.")
|
||||
|
||||
|
||||
class TraitRetrievalFailed(NovaException):
|
||||
msg_fmt = _("Failed to retrieve traits from the placement API: %(error)s")
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@ from wsgi_intercept import interceptor
|
|||
from nova.api.openstack.placement import deploy
|
||||
from nova import conf
|
||||
from nova import context
|
||||
# TODO(cdent): This points to the nova, not placement, exception for
|
||||
# InvalidResourceClass. This test should probably move out of the
|
||||
# placement hierarchy since it expects a "standard" placement server
|
||||
# and is not testing the placement service itself.
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova import rc_fields as fields
|
||||
|
|
|
@ -13,10 +13,10 @@ import os_traits
|
|||
from oslo_utils import uuidutils
|
||||
import sqlalchemy as sa
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement import lib as placement_lib
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova import context
|
||||
from nova import exception
|
||||
from nova import rc_fields as fields
|
||||
from nova import test
|
||||
from nova.tests import fixtures
|
||||
|
|
|
@ -15,8 +15,8 @@ import mock
|
|||
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.db.sqlalchemy import resource_class_cache as rc_cache
|
||||
from nova import exception
|
||||
from nova import rc_fields as fields
|
||||
from nova import test
|
||||
from nova.tests import fixtures
|
||||
|
|
|
@ -17,9 +17,9 @@ from oslo_db import exception as db_exc
|
|||
import sqlalchemy as sa
|
||||
|
||||
import nova
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement.objects import resource_provider as rp_obj
|
||||
from nova import context
|
||||
from nova import exception
|
||||
from nova import rc_fields as fields
|
||||
from nova import test
|
||||
from nova.tests import fixtures
|
||||
|
|
|
@ -16,10 +16,10 @@ import six
|
|||
from oslo_utils import timeutils
|
||||
|
||||
import nova
|
||||
from nova.api.openstack.placement import exception
|
||||
from nova.api.openstack.placement.objects import resource_provider
|
||||
from nova import context
|
||||
from nova.db.sqlalchemy import api_models as models
|
||||
from nova import exception
|
||||
from nova import rc_fields as fields
|
||||
from nova import test
|
||||
from nova.tests.unit.objects import test_objects
|
||||
|
|
Loading…
Reference in New Issue