| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- # Copyright 2010 United States Government as represented by the
- # Administrator of the National Aeronautics and Space Administration.
- # All Rights Reserved.
- #
- # 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.
- import sys
- from oslo_config import cfg
- from oslo_log import log as logging
- from oslo_versionedobjects import exception as obj_exc
- import six
- import webob.exc
- from webob.util import status_generic_reasons
- from webob.util import status_reasons
- from coriolis.i18n import _, _LE # noqa
- LOG = logging.getLogger(__name__)
- CONF = cfg.CONF
- TASK_ALREADY_CANCELLING_EXCEPTION_FMT = (
- "Task %(task_id)s is in CANCELLING status.")
- class ConvertedException(webob.exc.WSGIHTTPException):
- def __init__(self, code=500, title="", explanation=""):
- self.code = code
- # There is a strict rule about constructing status line for HTTP:
- # '...Status-Line, consisting of the protocol version followed by a
- # numeric status code and its associated textual phrase, with each
- # element separated by SP characters'
- # (http://www.faqs.org/rfcs/rfc2616.html)
- # 'code' and 'title' can not be empty because they correspond
- # to numeric status code and its associated text
- if title:
- self.title = title
- else:
- try:
- self.title = status_reasons[self.code]
- except KeyError:
- generic_code = self.code // 100
- self.title = status_generic_reasons[generic_code]
- self.explanation = explanation
- super(ConvertedException, self).__init__()
- class Error(Exception):
- pass
- class CoriolisException(Exception):
- """Base Coriolis Exception
- To correctly use this class, inherit from it and define
- a 'message' property. That message will get printf'd
- with the keyword arguments provided to the constructor.
- """
- message = _("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
- for k, v in self.kwargs.items():
- if isinstance(v, Exception):
- self.kwargs[k] = six.text_type(v)
- if self._should_format(message):
- try:
- message = self.message % 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(_LE('Exception in string format operation'))
- for name, value in kwargs.items():
- LOG.error(_LE("%(name)s: %(value)s"),
- {'name': name, 'value': value})
- if CONF.fatal_exception_format_errors:
- six.reraise(*exc_info)
- # at least get the core message out if something happened
- message = self.message
- elif isinstance(message, Exception):
- message = six.text_type(message)
- # NOTE(luisg): We put the actual message in 'msg' so that we can access
- # it, because if we try to access the message via 'message' it will be
- # overshadowed by the class' message attribute
- self.msg = message
- super(CoriolisException, self).__init__(message)
- def _should_format(self, message):
- return message is None or '%(message)' in self.message
- def __unicode__(self):
- return six.text_type(self.msg)
- class NotAuthorized(CoriolisException):
- message = _("Not authorized.")
- code = 403
- safe = True
- class PolicyNotAuthorized(CoriolisException):
- message = _("Policy doesn't allow %(action)s to be performed.")
- code = 403
- safe = True
- class Conflict(CoriolisException):
- message = _("Conflict")
- code = 409
- safe = True
- class AdminRequired(NotAuthorized):
- message = _("User does not have admin privileges")
- class Invalid(CoriolisException):
- message = _("Unacceptable parameters.")
- code = 400
- safe = True
- class InvalidMinionPoolSelection(Invalid):
- message = _("The selected minion pool is incompatible.")
- class InvalidMinionMachineState(Invalid):
- message = _("The selected minion machine is in an invalid state.")
- class MinionMachineAllocationFailure(Invalid):
- message = _("No minion machines were available for allocation")
- class InvalidCustomOSDetectTools(Invalid):
- message = _("The provided custom OS detect tools are invalid.")
- class InvalidOSMorphingTools(Invalid):
- message = _("Invalid OSMorphing tools received: %(tools_class)s")
- class InvalidDetectedOSParams(CoriolisException):
- message = _("One or more detected OS parameters were invalid.")
- safe = True
- class InvalidResults(Invalid):
- message = _("The results are invalid.")
- class InvalidInput(Invalid):
- message = _("Invalid input received: %(reason)s")
- class InvalidContentType(Invalid):
- message = _("Invalid content type %(content_type)s.")
- class InvalidHost(Invalid):
- message = _("Invalid host: %(reason)s")
- class SameDestination(Invalid):
- message = _("Origin and destination cannot be the same")
- # Cannot be templated as the error syntax varies.
- # msg needs to be constructed when raised.
- class InvalidParameterValue(Invalid):
- message = _("%(err)s")
- class InvalidAuthKey(Invalid):
- message = _("Invalid auth key: %(reason)s")
- class InvalidConfigurationValue(Invalid):
- message = _('Value "%(value)s" is not valid for '
- 'configuration option "%(option)s"')
- class InvalidTaskState(Invalid):
- message = _(
- 'Task "%(task_id)s" in in an invalid state: %(task_state)s')
- class InvalidMinionPoolState(Invalid):
- message = _(
- 'Minion pool "%(pool_id)s" in in an invalid state: %(pool_state)s')
- class TaskIsCancelling(InvalidTaskState):
- message = _(TASK_ALREADY_CANCELLING_EXCEPTION_FMT)
- class InvalidTaskResult(InvalidTaskState):
- message = _('Task returned an invalid result.')
- class InvalidActionTasksExecutionState(Invalid):
- message = _("Invalid tasks execution state: %(reason)s")
- class InvalidMigrationState(Invalid):
- message = _("Invalid migration state: %(reason)s")
- class InvalidReplicaState(Invalid):
- message = _("Invalid replica state: %(reason)s")
- class ServiceUnavailable(Invalid):
- message = _("Service is unavailable at this time.")
- class APIException(CoriolisException):
- message = _("Error while requesting %(service)s API.")
- safe = True
- def __init__(self, message=None, **kwargs):
- if 'service' not in kwargs:
- kwargs['service'] = 'unknown'
- super(APIException, self).__init__(message, **kwargs)
- class APITimeout(APIException):
- message = _("Timeout while requesting %(service)s API.")
- class NotFound(CoriolisException):
- message = _("Resource could not be found.")
- code = 404
- safe = True
- class RegionNotFound(NotFound):
- message = _("The specified Coriolis region(s) could not be found.")
- class OSMorphingToolsNotFound(NotFound):
- message = _(
- 'No OSMorphing tools were found for OS type "%(os_type)s" for this VM.'
- ' This would indicate that it was either not possible to determine the'
- ' exact OS release, or this OS release is not supported by Coriolis. '
- 'Suggestions include performing any needed OSMorphing steps manually '
- 'within the source VM and then re-syncing with the "Skip OS Morphing" '
- 'option enabled to bypass this stage, or contacting Cloudbase support '
- 'for further assistance.')
- class OSDetectToolsNotFound(NotFound):
- message = _(
- 'No "%(os_type)s" OS detect tools were able to identify the OS for this VM. '
- 'This would indicate that it was either not possible to determine the '
- 'exact OS release, or this OS release is not supported by Coriolis. '
- 'Suggestions include performing any needed OSMorphing steps manually '
- 'within the source VM and then re-syncing with the "Skip OS Morphing" '
- 'option enabled to bypass this stage, or contacting Cloudbase support '
- 'for further assistance.')
- class FileNotFound(NotFound):
- message = _("File %(file_path)s could not be found.")
- class InstanceNotFound(NotFound):
- message = _("Instance \"%(instance_name)s\" could not be found.")
- class NetworkNotFound(NotFound):
- message = _("Network \"%(network_name)s\" could not be found.")
- class DiskStorageMappingNotFound(NotFound):
- message = _('No storage mapping for disk with ID "%(id)s" could be found.')
- class StorageBackendNotFound(NotFound):
- message = _(
- 'Storage backend with name "%(storage_name)s" could not be found.')
- class ImageNotFound(NotFound):
- message = _("Image \"%(image_name)s\" could not be found.")
- class FlavorNotFound(NotFound):
- message = _("Flavor \"%(flavor_name)s\" could not be found.")
- class FloatingIPPoolNotFound(NotFound):
- message = _("Floating IP pool \"%(pool_name)s\" could not be found.")
- class VolumeNotFound(NotFound):
- message = _("Volume \"%(volume_id)s\" could not be found.")
- class VolumeSnapshotNotFound(NotFound):
- message = _("Volume snapshot \"%(snapshot_id)s\" could not be found.")
- class VolumeBackupNotFound(NotFound):
- message = _("Volume backup \"%(backup_id)s\" could not be found.")
- class Duplicate(CoriolisException):
- safe = True
- class MalformedRequestBody(CoriolisException):
- message = _("Malformed message body: %(reason)s")
- code = 400
- safe = True
- class ConfigNotFound(NotFound):
- message = _("Could not find config at %(path)s")
- class ParameterNotFound(NotFound):
- message = _("Could not find parameter %(param)s")
- class PasteAppNotFound(NotFound):
- message = _("Could not load paste app '%(name)s' from %(path)s")
- class NoValidHost(CoriolisException):
- message = _("No valid host was found. %(reason)s")
- safe = True
- UnsupportedObjectError = obj_exc.UnsupportedObjectError
- OrphanedObjectError = obj_exc.OrphanedObjectError
- IncompatibleObjectVersion = obj_exc.IncompatibleObjectVersion
- ReadOnlyFieldError = obj_exc.ReadOnlyFieldError
- ObjectActionError = obj_exc.ObjectActionError
- ObjectFieldInvalid = obj_exc.ObjectFieldInvalid
- class NotSupportedOperation(Invalid):
- message = _("Operation not supported: %(operation)s.")
- code = 405
- class TaskProcessException(CoriolisException):
- safe = True
- class TaskProcessCanceledException(TaskProcessException):
- pass
- class OperatingSystemNotFound(NotFound):
- pass
- class ConnectionValidationException(CoriolisException):
- safe = True
- class SchemaValidationException(CoriolisException):
- safe = True
- class QEMUException(Exception):
- pass
- if six.PY2:
- class ConnectionRefusedError(OSError):
- pass
- else:
- ConnectionRefusedError = six.moves.builtins.ConnectionRefusedError
- class UnrecognizedWorkerInitSystem(CoriolisException):
- message = _(
- "Could not determine init system for temporary worker VM. The image "
- "used for the worker VM must use systemd as an init system for "
- "Coriolis to be able to use it for data Replication.")
- class NoRegionError(CoriolisException):
- safe = True
- code = 503
- message = _(
- "No Coriolis region is avaialable to process this request at this "
- "time.")
- class NoSuitableRegionError(NoRegionError):
- message = _(
- "No Coriolis Region(s) fitting the criteria of the required operation "
- "could be found.")
- class NoServiceError(CoriolisException):
- safe = True
- code = 503
- message = _(
- "No service is avaialable to process this request at this time.")
- class NoWorkerServiceError(NoServiceError):
- message = _(
- "No Coriolis Worker Service(s) were found. Please ensure that "
- "at least one or Coriolis Worker Service(s) are registered "
- "within the Coriolis installation.")
- class NoSuitableWorkerServiceError(NoServiceError):
- message = _(
- "No suitable Coriolis Worker service was found which fits the "
- "criteria for the required operation.")
- class OSMorphingException(CoriolisException):
- pass
- class PackageManagerOperationException(OSMorphingException):
- pass
- class FailedPackageInstallationException(PackageManagerOperationException):
- message = (
- "Failed to install required packages %(package_names)s through "
- "%(package_manager)s. Please ensure that the required packages are "
- "available within the %(package_manager)s repositories configured "
- "within the source machine. If not, please either add or enable "
- "additional repositories within the source machine which contain the "
- "packages Coriolis requires, or attempt to manually install the "
- "packages on the source machine and then migrate the VM using Coriolis"
- " with the OSMorphing process disabled. Error was: %(error)s")
- class FailedPackageUninstallationException(PackageManagerOperationException):
- message = (
- "Failed to remove unwanted packages (%(package_names)s) through "
- "%(package_manager)s. Error was: %(error)s")
- class MinionMachineCommandTimeout(CoriolisException):
- pass
- class OSMorphingOperationTimeout(MinionMachineCommandTimeout):
- pass
- class OSMorphingSSHOperationTimeout(OSMorphingOperationTimeout):
- message = (
- "Pending SSH command %(cmd)s timed out after %(timeout)s seconds. "
- "Coriolis may have encountered connection issues to the minion machine"
- " or the command execution time exceeds the timeout set. Try extending"
- " the timeout by editing the 'default_osmorphing_operation_timeout' "
- "in Coriolis' static configuration file."
- )
- class OSMorphingWinRMOperationTimeout(OSMorphingOperationTimeout):
- message = (
- "Pending WinRM command %(cmd)s timed out after %(timeout)s seconds. "
- "Coriolis may have encountered connection issues to the minion machine"
- " or the command execution time exceeds the timeout set. Try extending"
- " the timeout by editing the 'default_osmorphing_operation_timeout' "
- "in Coriolis' static configuration file."
- )
|