cinder/cinder/message/message_field.py

167 lines
6.0 KiB
Python

# 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.
"""Message Resource, Action, Detail and user visible message.
Use Resource, Action and Detail's combination to indicate the Event
in the format of:
EVENT: VOLUME_RESOURCE_ACTION_DETAIL
Also, use exception-to-detail mapping to decrease the workload of
classifying event in cinder's task code.
"""
from cinder.i18n import _
class Resource(object):
VOLUME = 'VOLUME'
VOLUME_SNAPSHOT = 'VOLUME_SNAPSHOT'
class Action(object):
SCHEDULE_ALLOCATE_VOLUME = ('001', _('schedule allocate volume'))
ATTACH_VOLUME = ('002', _('attach volume'))
COPY_VOLUME_TO_IMAGE = ('003', _('copy volume to image'))
UPDATE_ATTACHMENT = ('004', _('update attachment'))
COPY_IMAGE_TO_VOLUME = ('005', _('copy image to volume'))
UNMANAGE_VOLUME = ('006', _('unmanage volume'))
EXTEND_VOLUME = ('007', _('extend volume'))
CREATE_VOLUME_FROM_BACKEND = ('008',
_('create volume from backend storage'))
SNAPSHOT_CREATE = ('009', _('create snapshot'))
SNAPSHOT_DELETE = ('010', _('delete snapshot'))
SNAPSHOT_UPDATE = ('011', _('update snapshot'))
SNAPSHOT_METADATA_UPDATE = ('012', _('update snapshot metadata'))
ALL = (SCHEDULE_ALLOCATE_VOLUME,
ATTACH_VOLUME,
COPY_VOLUME_TO_IMAGE,
UPDATE_ATTACHMENT,
COPY_IMAGE_TO_VOLUME,
UNMANAGE_VOLUME,
EXTEND_VOLUME,
CREATE_VOLUME_FROM_BACKEND,
SNAPSHOT_CREATE,
SNAPSHOT_DELETE,
SNAPSHOT_UPDATE,
SNAPSHOT_METADATA_UPDATE,
)
class Detail(object):
UNKNOWN_ERROR = ('001', _('An unknown error occurred.'))
DRIVER_NOT_INITIALIZED = ('002',
_('Driver is not initialized at present.'))
NO_BACKEND_AVAILABLE = ('003',
_('Could not find any available '
'weighted backend.'))
FAILED_TO_UPLOAD_VOLUME = ('004',
_("Failed to upload volume to image "
"at backend."))
VOLUME_ATTACH_MODE_INVALID = ('005',
_("Volume's attach mode is invalid."))
QUOTA_EXCEED = ('006',
_("Not enough quota resource for operation."))
NOT_ENOUGH_SPACE_FOR_IMAGE = ('007',
_("Image used for creating volume exceeds "
"available space."))
UNMANAGE_ENC_NOT_SUPPORTED = (
'008',
_("Unmanaging encrypted volumes is not supported."))
NOTIFY_COMPUTE_SERVICE_FAILED = (
'009',
_("Compute service failed to extend volume."))
DRIVER_FAILED_EXTEND = (
'010',
_("Volume Driver failed to extend volume."))
SIGNATURE_VERIFICATION_FAILED = (
'011',
_("Image signature verification failed."))
DRIVER_FAILED_CREATE = (
'012',
_('Driver failed to create the volume.'))
SNAPSHOT_CREATE_ERROR = ('013', _("Snapshot failed to create."))
SNAPSHOT_UPDATE_METADATA_FAILED = (
'014',
_("Volume snapshot update metadata failed."))
SNAPSHOT_IS_BUSY = ('015', _("Snapshot is busy."))
SNAPSHOT_DELETE_ERROR = ('016', _("Snapshot failed to delete."))
ALL = (UNKNOWN_ERROR,
DRIVER_NOT_INITIALIZED,
NO_BACKEND_AVAILABLE,
FAILED_TO_UPLOAD_VOLUME,
VOLUME_ATTACH_MODE_INVALID,
QUOTA_EXCEED,
NOT_ENOUGH_SPACE_FOR_IMAGE,
UNMANAGE_ENC_NOT_SUPPORTED,
NOTIFY_COMPUTE_SERVICE_FAILED,
DRIVER_FAILED_EXTEND,
SIGNATURE_VERIFICATION_FAILED,
DRIVER_FAILED_CREATE,
SNAPSHOT_CREATE_ERROR,
SNAPSHOT_UPDATE_METADATA_FAILED,
SNAPSHOT_IS_BUSY,
SNAPSHOT_DELETE_ERROR,
)
# Exception and detail mappings
EXCEPTION_DETAIL_MAPPINGS = {
DRIVER_NOT_INITIALIZED: ['DriverNotInitialized'],
NO_BACKEND_AVAILABLE: ['NoValidBackend'],
VOLUME_ATTACH_MODE_INVALID: ['InvalidVolumeAttachMode'],
QUOTA_EXCEED: ['ImageLimitExceeded',
'BackupLimitExceeded',
'SnapshotLimitExceeded'],
NOT_ENOUGH_SPACE_FOR_IMAGE: ['ImageTooBig'],
SNAPSHOT_IS_BUSY: ['SnapshotIsBusy'],
}
def translate_action(action_id):
action_message = next((action[1] for action in Action.ALL
if action[0] == action_id), None)
return action_message or 'unknown action'
def translate_detail(detail_id):
detail_message = next((action[1] for action in Detail.ALL
if action[0] == detail_id), None)
return detail_message or Detail.UNKNOWN_ERROR[1]
def translate_detail_id(exception, detail):
"""Get a detail_id to use for a message.
If exception is in the EXCEPTION_DETAIL_MAPPINGS, returns the detail_id
of the mapped Detail field. If exception is not in the mapping or is None,
returns the detail_id of the passed-in Detail field. Otherwise, returns
the detail_id of Detail.UNKNOWN_ERROR.
:param exception: an Exception (or None)
:param detail: a message_field.Detail field (or None)
:returns: string
:returns: the detail_id of a message_field.Detail field
"""
if exception is not None and isinstance(exception, Exception):
for key, value in Detail.EXCEPTION_DETAIL_MAPPINGS.items():
if exception.__class__.__name__ in value:
return key[0]
if detail in Detail.ALL:
return detail[0]
return Detail.UNKNOWN_ERROR[0]