683 lines
18 KiB
Python
683 lines
18 KiB
Python
# Copyright 2011 OpenStack Foundation
|
|
# 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.
|
|
"""I totally stole most of this from melange, thx guys!!!"""
|
|
|
|
|
|
import re
|
|
|
|
from oslo_concurrency import processutils
|
|
from oslo_log import log as logging
|
|
|
|
from trove.common import base_exception as openstack_exception
|
|
from trove.common.i18n import _
|
|
|
|
|
|
ClientConnectionError = openstack_exception.ClientConnectionError
|
|
ProcessExecutionError = processutils.ProcessExecutionError
|
|
DatabaseMigrationError = openstack_exception.DatabaseMigrationError
|
|
LOG = logging.getLogger(__name__)
|
|
wrap_exception = openstack_exception.wrap_exception
|
|
|
|
|
|
def safe_fmt_string(text):
|
|
return re.sub(r'%([0-9]+)', r'\1', text)
|
|
|
|
|
|
class TroveError(openstack_exception.OpenstackException):
|
|
"""Base exception that all custom trove app exceptions inherit from."""
|
|
internal_message = None
|
|
|
|
def __init__(self, message=None, **kwargs):
|
|
if message is not None:
|
|
self.message = message
|
|
if self.internal_message is not None:
|
|
try:
|
|
LOG.error(safe_fmt_string(self.internal_message), kwargs)
|
|
except Exception:
|
|
LOG.error(self.internal_message)
|
|
self.message = safe_fmt_string(self.message)
|
|
super(TroveError, self).__init__(**kwargs)
|
|
|
|
|
|
class DBConstraintError(TroveError):
|
|
|
|
message = _("Failed to save %(model_name)s because: %(error)s.")
|
|
|
|
|
|
class InvalidRPCConnectionReuse(TroveError):
|
|
|
|
message = _("Invalid RPC Connection Reuse.")
|
|
|
|
|
|
class NotFound(TroveError):
|
|
|
|
message = _("Resource %(uuid)s cannot be found.")
|
|
|
|
|
|
class CapabilityNotFound(NotFound):
|
|
|
|
message = _("Capability '%(capability)s' cannot be found.")
|
|
|
|
|
|
class CapabilityDisabled(TroveError):
|
|
|
|
message = _("Capability '%(capability)s' is disabled.")
|
|
|
|
|
|
class FlavorNotFound(TroveError):
|
|
|
|
message = _("Resource %(uuid)s cannot be found.")
|
|
|
|
|
|
class UserNotFound(NotFound):
|
|
|
|
message = _("User %(uuid)s cannot be found on the instance.")
|
|
|
|
|
|
class RootHistoryNotFound(NotFound):
|
|
|
|
message = _("Root user has never been enabled on the instance.")
|
|
|
|
|
|
class DatabaseNotFound(NotFound):
|
|
|
|
message = _("Database %(uuid)s cannot be found on the instance.")
|
|
|
|
|
|
class ComputeInstanceNotFound(NotFound):
|
|
|
|
# internal_message is used for log, stop translating.
|
|
internal_message = ("Cannot find compute instance %(server_id)s for "
|
|
"instance %(instance_id)s.")
|
|
|
|
message = _("Resource %(instance_id)s can not be retrieved.")
|
|
|
|
|
|
class DnsRecordNotFound(NotFound):
|
|
|
|
message = _("DnsRecord with name= %(name)s not found.")
|
|
|
|
|
|
class DatastoreNotFound(NotFound):
|
|
|
|
message = _("Datastore '%(datastore)s' cannot be found.")
|
|
|
|
|
|
class DatastoreVersionNotFound(NotFound):
|
|
|
|
message = _("Datastore version '%(version)s' cannot be found.")
|
|
|
|
|
|
class DatastoresNotFound(NotFound):
|
|
|
|
message = _("Datastores cannot be found.")
|
|
|
|
|
|
class DatastoreFlavorAssociationNotFound(NotFound):
|
|
|
|
message = _("Flavor %(id)s is not supported for datastore "
|
|
"%(datastore)s version %(datastore_version)s")
|
|
|
|
|
|
class DatastoreFlavorAssociationAlreadyExists(TroveError):
|
|
|
|
message = _("Flavor %(id)s is already associated with "
|
|
"datastore %(datastore)s version %(datastore_version)s")
|
|
|
|
|
|
class DatastoreVolumeTypeAssociationNotFound(NotFound):
|
|
|
|
message = _("The volume type %(id)s is not valid for datastore "
|
|
"%(datastore)s and version %(version_id)s.")
|
|
|
|
|
|
class DatastoreVolumeTypeAssociationAlreadyExists(TroveError):
|
|
|
|
message = _("Datastore '%(datastore)s' version %(datastore_version)s "
|
|
"and volume-type %(id)s mapping already exists.")
|
|
|
|
|
|
class DataStoreVersionVolumeTypeRequired(TroveError):
|
|
|
|
message = _("Only specific volume types are allowed for a "
|
|
"datastore %(datastore)s version %(datastore_version)s. "
|
|
"You must specify a valid volume type.")
|
|
|
|
|
|
class DatastoreVersionNoVolumeTypes(TroveError):
|
|
|
|
message = _("No valid volume types could be found for datastore "
|
|
"%(datastore)s and version %(datastore_version)s.")
|
|
|
|
|
|
class DatastoreNoVersion(TroveError):
|
|
|
|
message = _("Datastore '%(datastore)s' has no version '%(version)s'.")
|
|
|
|
|
|
class DatastoreVersionInactive(TroveError):
|
|
|
|
message = _("Datastore version '%(version)s' is not active.")
|
|
|
|
|
|
class DatastoreDefaultDatastoreNotFound(TroveError):
|
|
|
|
message = _("Please specify datastore. Default datastore "
|
|
"'%(datastore)s' cannot be found.")
|
|
|
|
|
|
class DatastoreDefaultDatastoreNotDefined(TroveError):
|
|
|
|
message = _("Please specify datastore. No default datastore "
|
|
"is defined.")
|
|
|
|
|
|
class DatastoreDefaultVersionNotFound(TroveError):
|
|
|
|
message = _("Default version for datastore '%(datastore)s' not found.")
|
|
|
|
|
|
class InvalidDatastoreManager(TroveError):
|
|
|
|
message = _("Datastore manager %(datastore_manager)s cannot be found.")
|
|
|
|
|
|
class DatastoreOperationNotSupported(TroveError):
|
|
|
|
message = _("The '%(operation)s' operation is not supported for "
|
|
"the '%(datastore)s' datastore.")
|
|
|
|
|
|
class NoUniqueMatch(TroveError):
|
|
|
|
message = _("Multiple matches found for '%(name)s', "
|
|
"use an UUID to be more specific.")
|
|
|
|
|
|
class OverLimit(TroveError):
|
|
|
|
# internal_message is used for log, stop translating.
|
|
internal_message = ("The server rejected the request due to its size or "
|
|
"rate.")
|
|
|
|
|
|
class QuotaLimitTooSmall(TroveError):
|
|
|
|
message = _("Quota limit '%(limit)s' for '%(resource)s' is too small"
|
|
" - must be at least '-1'.")
|
|
|
|
|
|
class QuotaExceeded(TroveError):
|
|
|
|
message = _("Quota exceeded for resources: %(overs)s.")
|
|
|
|
|
|
class VolumeQuotaExceeded(QuotaExceeded):
|
|
|
|
message = _("Instance volume quota exceeded.")
|
|
|
|
|
|
class GuestError(TroveError):
|
|
|
|
message = _("An error occurred communicating with the guest: "
|
|
"%(original_message)s.")
|
|
|
|
|
|
class GuestTimeout(TroveError):
|
|
|
|
message = _("Timeout trying to connect to the Guest Agent.")
|
|
|
|
|
|
class BadRequest(TroveError):
|
|
|
|
message = _("The server could not comply with the request since it is "
|
|
"either malformed or otherwise incorrect.")
|
|
|
|
|
|
class MissingKey(BadRequest):
|
|
|
|
message = _("Required element/key - %(key)s was not specified.")
|
|
|
|
|
|
class DatabaseAlreadyExists(BadRequest):
|
|
|
|
message = _('A database with the name "%(name)s" already exists.')
|
|
|
|
|
|
class UserAlreadyExists(BadRequest):
|
|
|
|
message = _('A user with the name "%(name)s" already exists.')
|
|
|
|
|
|
class InstanceAssignedToConfiguration(BadRequest):
|
|
|
|
message = _('A configuration group cannot be deleted if it is '
|
|
'associated with one or more non-terminated instances. '
|
|
'Detach the configuration group from all non-terminated '
|
|
'instances and please try again.')
|
|
|
|
|
|
class UnprocessableEntity(TroveError):
|
|
|
|
message = _("Unable to process the contained request.")
|
|
|
|
|
|
class ConfigurationNotSupported(UnprocessableEntity):
|
|
|
|
message = _("Configuration groups not supported by the datastore.")
|
|
|
|
|
|
class CannotResizeToSameSize(TroveError):
|
|
|
|
message = _("No change was requested in the size of the instance.")
|
|
|
|
|
|
class VolumeAttachmentsNotFound(NotFound):
|
|
|
|
message = _("Cannot find the volumes attached to compute "
|
|
"instance %(server_id)s.")
|
|
|
|
|
|
class VolumeCreationFailure(TroveError):
|
|
|
|
message = _("Failed to create a volume in Nova.")
|
|
|
|
|
|
class VolumeSizeNotSpecified(BadRequest):
|
|
|
|
message = _("Volume size was not specified.")
|
|
|
|
|
|
class LocalStorageNotSpecified(BadRequest):
|
|
|
|
message = _("Local storage not specified in flavor ID: %(flavor)s.")
|
|
|
|
|
|
class LocalStorageNotSupported(TroveError):
|
|
|
|
message = _("Local storage support is not enabled.")
|
|
|
|
|
|
class VolumeNotSupported(TroveError):
|
|
|
|
message = _("Volume support is not enabled.")
|
|
|
|
|
|
class ReplicationNotSupported(TroveError):
|
|
|
|
message = _("Replication is not supported for "
|
|
"the '%(datastore)s' datastore.")
|
|
|
|
|
|
class ReplicationSlaveAttachError(TroveError):
|
|
|
|
message = _("Exception encountered attaching slave to new replica source.")
|
|
|
|
|
|
class TaskManagerError(TroveError):
|
|
|
|
message = _("An error occurred communicating with the task manager: "
|
|
"%(original_message)s.")
|
|
|
|
|
|
class BadValue(TroveError):
|
|
|
|
message = _("Value could not be converted: %(msg)s.")
|
|
|
|
|
|
class PollTimeOut(TroveError):
|
|
|
|
message = _("Polling request timed out.")
|
|
|
|
|
|
class Forbidden(TroveError):
|
|
|
|
message = _("User does not have admin privileges.")
|
|
|
|
|
|
class PolicyNotAuthorized(Forbidden):
|
|
|
|
message = _("Policy doesn't allow %(action)s to be performed.")
|
|
|
|
|
|
class InvalidModelError(TroveError):
|
|
|
|
message = _("The following values are invalid: %(errors)s.")
|
|
|
|
|
|
class ModelNotFoundError(NotFound):
|
|
|
|
message = _("Not Found.")
|
|
|
|
|
|
class UpdateGuestError(TroveError):
|
|
|
|
message = _("Failed to update instances.")
|
|
|
|
|
|
class ConfigNotFound(NotFound):
|
|
|
|
message = _("Config file not found.")
|
|
|
|
|
|
class PasteAppNotFound(NotFound):
|
|
|
|
message = _("Paste app not found.")
|
|
|
|
|
|
class QuotaNotFound(NotFound):
|
|
message = _("Quota could not be found.")
|
|
|
|
|
|
class TenantQuotaNotFound(QuotaNotFound):
|
|
message = _("Quota for tenant %(tenant_id)s could not be found.")
|
|
|
|
|
|
class QuotaResourceUnknown(QuotaNotFound):
|
|
message = _("Unknown quota resources %(unknown)s.")
|
|
|
|
|
|
class BackupUploadError(TroveError):
|
|
message = _("Unable to upload Backup to swift.")
|
|
|
|
|
|
class BackupDownloadError(TroveError):
|
|
message = _("Unable to download Backup from swift")
|
|
|
|
|
|
class BackupCreationError(TroveError):
|
|
message = _("Unable to create Backup.")
|
|
|
|
|
|
class BackupUpdateError(TroveError):
|
|
message = _("Unable to update Backup table in database.")
|
|
|
|
|
|
class SecurityGroupDeletionError(TroveError):
|
|
|
|
message = _("Failed to delete Security Group.")
|
|
|
|
|
|
class SecurityGroupRuleDeletionError(TroveError):
|
|
|
|
message = _("Failed to delete Security Group Rule.")
|
|
|
|
|
|
class BackupNotCompleteError(TroveError):
|
|
|
|
message = _("Unable to create instance because backup %(backup_id)s is "
|
|
"not completed. Actual state: %(state)s.")
|
|
|
|
|
|
class BackupFileNotFound(NotFound):
|
|
message = _("Backup file in %(location)s was not found in the object "
|
|
"storage.")
|
|
|
|
|
|
class BackupDatastoreMismatchError(TroveError):
|
|
message = _("The datastore from which the backup was taken, "
|
|
"%(datastore1)s, does not match the destination"
|
|
" datastore of %(datastore2)s.")
|
|
|
|
|
|
class ReplicaCreateWithUsersDatabasesError(TroveError):
|
|
message = _("Cannot create a replica with users or databases.")
|
|
|
|
|
|
class SwiftAuthError(TroveError):
|
|
message = _("Swift account not accessible for tenant %(tenant_id)s.")
|
|
|
|
|
|
class SwiftNotFound(TroveError):
|
|
message = _("Swift is disabled for tenant %(tenant_id)s.")
|
|
|
|
|
|
class SwiftConnectionError(TroveError):
|
|
message = _("Cannot connect to Swift.")
|
|
|
|
|
|
class DatabaseForUserNotInDatabaseListError(TroveError):
|
|
message = _("The request indicates that user %(user)s should have access "
|
|
"to database %(database)s, but database %(database)s is not "
|
|
"included in the initial databases list.")
|
|
|
|
|
|
class DatabaseInitialDatabaseDuplicateError(TroveError):
|
|
message = _("Two or more databases share the same name in the initial "
|
|
"databases list. Please correct the names or remove the "
|
|
"duplicate entries.")
|
|
|
|
|
|
class DatabaseInitialUserDuplicateError(TroveError):
|
|
message = _("Two or more users share the same name and host in the "
|
|
"initial users list. Please correct the names or remove the "
|
|
"duplicate entries.")
|
|
|
|
|
|
class RestoreBackupIntegrityError(TroveError):
|
|
message = _("Current Swift object checksum does not match original "
|
|
"checksum for backup %(backup_id)s.")
|
|
|
|
|
|
class ConfigKeyNotFound(NotFound):
|
|
message = _("%(key)s is not a supported configuration parameter.")
|
|
|
|
|
|
class NoConfigParserFound(NotFound):
|
|
message = _("No configuration parser found for datastore "
|
|
"%(datastore_manager)s.")
|
|
|
|
|
|
class ConfigurationDatastoreNotMatchInstance(TroveError):
|
|
message = _("Datastore Version on Configuration "
|
|
"%(config_datastore_version)s does not "
|
|
"match the Datastore Version on the instance "
|
|
"%(instance_datastore_version)s.")
|
|
|
|
|
|
class ConfigurationParameterDeleted(TroveError):
|
|
message = _("%(parameter_name)s parameter can no longer be "
|
|
"set as of %(parameter_deleted_at)s.")
|
|
|
|
|
|
class ConfigurationParameterAlreadyExists(TroveError):
|
|
message = _("%(parameter_name)s parameter already exists "
|
|
"for datastore version %(datastore_version)s.")
|
|
|
|
|
|
class ConfigurationAlreadyAttached(TroveError):
|
|
message = _("Instance %(instance_id)s already has a "
|
|
"Configuration Group attached: %(configuration_id)s.")
|
|
|
|
|
|
class InvalidInstanceState(TroveError):
|
|
message = _("The operation you have requested cannot be executed because "
|
|
"the instance status is currently: %(status)s.")
|
|
|
|
|
|
class NoServiceEndpoint(TroveError):
|
|
"""Could not find requested endpoint in Service Catalog."""
|
|
message = _("Endpoint not found for service_type=%(service_type)s, "
|
|
"endpoint_type=%(endpoint_type)s, "
|
|
"endpoint_region=%(endpoint_region)s.")
|
|
|
|
|
|
class EmptyCatalog(NoServiceEndpoint):
|
|
"""The service catalog is empty."""
|
|
message = _("Empty catalog.")
|
|
|
|
|
|
class IncompatibleReplicationStrategy(TroveError):
|
|
message = _("Instance with replication strategy %(guest_strategy)s "
|
|
"cannot replicate from instance with replication strategy "
|
|
"%(replication_strategy)s.")
|
|
|
|
|
|
class InsufficientSpaceForReplica(TroveError):
|
|
message = _("The target instance has only %(slave_volume_size)sG free, "
|
|
"but the replication snapshot contains %(dataset_size)sG "
|
|
"of data.")
|
|
|
|
|
|
class InsufficientSpaceForBackup(TroveError):
|
|
message = _("The instance has only %(free)sG free while the estimated "
|
|
"backup size is %(backup_size)sG.")
|
|
|
|
|
|
class ReplicaSourceDeleteForbidden(Forbidden):
|
|
message = _("The replica source cannot be deleted without detaching the "
|
|
"replicas.")
|
|
|
|
|
|
class ModuleTypeNotFound(NotFound):
|
|
message = _("Module type '%(module_type)s' was not found.")
|
|
|
|
|
|
class ModuleAppliedToInstance(BadRequest):
|
|
|
|
message = _("A module cannot be deleted or its contents modified if it "
|
|
"has been applied to a non-terminated instance, unless the "
|
|
"module has been marked as 'live_update.' "
|
|
"Please remove the module from all non-terminated "
|
|
"instances and try again.")
|
|
|
|
|
|
class ModuleAlreadyExists(BadRequest):
|
|
|
|
message = _("A module with the name '%(name)s' already exists for "
|
|
"datastore '%(datastore)s' and datastore version "
|
|
"'%(ds_version)s'")
|
|
|
|
|
|
class ModuleAccessForbidden(Forbidden):
|
|
|
|
message = _("You must be admin to %(action)s a module with these "
|
|
"options. %(options)s")
|
|
|
|
|
|
class ModuleInvalid(Forbidden):
|
|
|
|
message = _("The module is invalid: %(reason)s")
|
|
|
|
|
|
class InstanceNotFound(NotFound):
|
|
message = _("Instance '%(instance)s' cannot be found.")
|
|
|
|
|
|
class ClusterNotFound(NotFound):
|
|
message = _("Cluster '%(cluster)s' cannot be found.")
|
|
|
|
|
|
class ClusterFlavorsNotEqual(TroveError):
|
|
message = _("The flavor for each instance in a cluster must be the same.")
|
|
|
|
|
|
class ClusterNetworksNotEqual(TroveError):
|
|
message = _("The network for each instance in a cluster must be the same.")
|
|
|
|
|
|
class NetworkNotFound(TroveError):
|
|
message = _("Network Resource %(uuid)s cannot be found.")
|
|
|
|
|
|
class PublicNetworkNotFound(TroveError):
|
|
message = _("Public network cannot be found.")
|
|
|
|
|
|
class ClusterVolumeSizeRequired(TroveError):
|
|
message = _("A volume size is required for each instance in the cluster.")
|
|
|
|
|
|
class ClusterVolumeSizesNotEqual(TroveError):
|
|
message = _("The volume size for each instance in a cluster must be "
|
|
"the same.")
|
|
|
|
|
|
class ClusterNumInstancesNotSupported(TroveError):
|
|
message = _("The number of instances for your initial cluster must "
|
|
"be %(num_instances)s.")
|
|
|
|
|
|
class ClusterNumInstancesNotLargeEnough(TroveError):
|
|
message = _("The number of instances for your initial cluster must "
|
|
"be at least %(num_instances)s.")
|
|
|
|
|
|
class ClusterNumInstancesBelowSafetyThreshold(TroveError):
|
|
message = _("The number of instances in your cluster cannot "
|
|
"safely be lowered below the current level based "
|
|
"on your current fault-tolerance settings.")
|
|
|
|
|
|
class ClusterShrinkMustNotLeaveClusterEmpty(TroveError):
|
|
message = _("Must leave at least one instance in the cluster when "
|
|
"shrinking.")
|
|
|
|
|
|
class ClusterShrinkInstanceInUse(TroveError):
|
|
message = _("Instance(s) %(id)s currently in use and cannot be deleted. "
|
|
"Details: %(reason)s")
|
|
|
|
|
|
class ClusterInstanceOperationNotSupported(TroveError):
|
|
message = _("Operation not supported for instances that are part of a "
|
|
"cluster.")
|
|
|
|
|
|
class ClusterOperationNotSupported(TroveError):
|
|
|
|
message = _("The '%(operation)s' operation is not supported for cluster.")
|
|
|
|
|
|
class TroveOperationAuthError(TroveError):
|
|
message = _("Operation not allowed for tenant %(tenant_id)s.")
|
|
|
|
|
|
class ClusterDatastoreNotSupported(TroveError):
|
|
message = _("Clusters not supported for "
|
|
"%(datastore)s-%(datastore_version)s.")
|
|
|
|
|
|
class BackupTooLarge(TroveError):
|
|
message = _("Backup is too large for given flavor or volume. "
|
|
"Backup size: %(backup_size)s GBs. "
|
|
"Available size: %(disk_size)s GBs.")
|
|
|
|
|
|
class ImageNotFound(NotFound):
|
|
|
|
message = _("Image %(uuid)s cannot be found.")
|
|
|
|
|
|
class DatastoreVersionAlreadyExists(BadRequest):
|
|
|
|
message = _("A datastore version with the name '%(name)s' already exists.")
|
|
|
|
|
|
class LogAccessForbidden(Forbidden):
|
|
|
|
message = _("You must be admin to %(action)s log '%(log)s'.")
|
|
|
|
|
|
class LogsNotAvailable(Forbidden):
|
|
|
|
message = _("Log actions are not supported.")
|
|
|
|
|
|
class SlaveOperationNotSupported(TroveError):
|
|
|
|
message = _("The '%(operation)s' operation is not supported for slaves in "
|
|
"replication.")
|