From 8b6f41715c4a4a8554444d634fbe62f73aa084d2 Mon Sep 17 00:00:00 2001 From: John Griffith Date: Mon, 11 Nov 2013 14:57:44 -0700 Subject: [PATCH] Subclass vendor specific exceptions. Up until now drivers have been able to define their own custom exception classes. In most cases these are inherited from either a native python exception class or at best the base cinder exception class. The problem with this is that it makes it very difficult for higher layers (such as volume manager) to do any intelligent exception handling and the base Cinder.exception class is too broad. This change takes the first step in cleaning this up. We create new exception classes for all drivers to inherit from: VolumeDriverException VolumeBackendAPIException BackupDriverException This still allows the freedom to create custom exceptions for a particular driver, however it also gives us a common exception class to catch and check in higher levels. Further refinement and standardization will be helpful going forward but this should give us a good start. Change-Id: I8c2ca4eecf7a64a82846d6d24fc0239db086237e --- cinder/exception.py | 231 ++++++++++++++++------------- cinder/tests/test_glusterfs.py | 3 +- cinder/tests/test_nfs.py | 2 +- cinder/tests/test_solidfire.py | 4 +- cinder/volume/drivers/solidfire.py | 3 +- 5 files changed, 138 insertions(+), 105 deletions(-) diff --git a/cinder/exception.py b/cinder/exception.py index a73ff12c9..5517aff05 100644 --- a/cinder/exception.py +++ b/cinder/exception.py @@ -106,6 +106,19 @@ class CinderException(Exception): return unicode(self.msg) +class VolumeBackendAPIException(CinderException): + message = _("Bad or unexpected response from the storage volume " + "backend API: %(data)s") + + +class VolumeDriverException(CinderException): + message = _("Volume driver reported an error: %(message)s") + + +class BackupDriverException(CinderException): + message = _("Backup driver reported an error: %(message)s") + + class GlanceConnectionFailed(CinderException): message = _("Connection to glance failed: %(reason)s") @@ -218,11 +231,6 @@ class VolumeNotFound(NotFound): message = _("Volume %(volume_id)s could not be found.") -class SfAccountNotFound(NotFound): - message = _("Unable to locate account %(account_name)s on " - "Solidfire device") - - class VolumeMetadataNotFound(NotFound): message = _("Volume %(volume_id)s has no metadata with " "key %(metadata_key)s.") @@ -417,92 +425,31 @@ class DuplicateSfVolumeNames(Duplicate): message = _("Detected more than one volume with name %(vol_name)s") -class Invalid3PARDomain(CinderException): - message = _("Invalid 3PAR Domain: %(err)s") - - class VolumeTypeCreateFailed(CinderException): message = _("Cannot create volume_type with " "name %(name)s and specs %(extra_specs)s") -class SolidFireAPIException(CinderException): - message = _("Bad response from SolidFire API") - - -class SolidFireAPIDataException(SolidFireAPIException): - message = _("Error in SolidFire API response: data=%(data)s") - - -class UnknownCmd(Invalid): +class UnknownCmd(VolumeDriverException): message = _("Unknown or unsupported command %(cmd)s") -class MalformedResponse(Invalid): +class MalformedResponse(VolumeDriverException): message = _("Malformed response to command %(cmd)s: %(reason)s") -class BadHTTPResponseStatus(CinderException): - message = _("Bad HTTP response status %(status)s") +class BadDriverResponseStatus(VolumeDriverException): + message = _("Bad driver response status: %(status)s") -class FailedCmdWithDump(CinderException): +class FailedCmdWithDump(VolumeDriverException): message = _("Operation failed with status=%(status)s. Full dump: %(data)s") -class ZadaraServerCreateFailure(CinderException): - message = _("Unable to create server object for initiator %(name)s") - - -class ZadaraServerNotFound(NotFound): - message = _("Unable to find server object for initiator %(name)s") - - -class ZadaraVPSANoActiveController(CinderException): - message = _("Unable to find any active VPSA controller") - - -class ZadaraAttachmentsNotFound(NotFound): - message = _("Failed to retrieve attachments for volume %(name)s") - - -class ZadaraInvalidAttachmentInfo(Invalid): - message = _("Invalid attachment info for volume %(name)s: %(reason)s") - - class InstanceNotFound(NotFound): message = _("Instance %(instance_id)s could not be found.") -class VolumeBackendAPIException(CinderException): - message = _("Bad or unexpected response from the storage volume " - "backend API: %(data)s") - - -class NfsException(CinderException): - message = _("Unknown NFS exception") - - -class NfsNoSharesMounted(NotFound): - message = _("No mounted NFS shares found") - - -class NfsNoSuitableShareFound(NotFound): - message = _("There is no share which can host %(volume_size)sG") - - -class GlusterfsException(CinderException): - message = _("Unknown Gluster exception") - - -class GlusterfsNoSharesMounted(NotFound): - message = _("No mounted Gluster shares found") - - -class GlusterfsNoSuitableShareFound(NotFound): - message = _("There is no share which can host %(volume_size)sG") - - class GlanceMetadataExists(Invalid): message = _("Glance metadata cannot be updated, key %(key)s" " exists for volume id %(volume_id)s") @@ -532,7 +479,7 @@ class ImageCopyFailure(Invalid): message = _("Failed to copy image to volume: %(reason)s") -class BackupInvalidCephArgs(Invalid): +class BackupInvalidCephArgs(BackupDriverException): message = _("Invalid Ceph args provided for backup rbd operation") @@ -540,7 +487,7 @@ class BackupOperationError(Invalid): message = _("An error has occurred during backup operation") -class BackupRBDOperationFailed(Invalid): +class BackupRBDOperationFailed(BackupDriverException): message = _("Backup RBD operation failed") @@ -556,7 +503,7 @@ class InvalidBackup(Invalid): message = _("Invalid backup: %(reason)s") -class SwiftConnectionFailed(CinderException): +class SwiftConnectionFailed(BackupDriverException): message = _("Connection to swift failed: %(reason)s") @@ -572,7 +519,54 @@ class SSHInjectionThreat(CinderException): message = _("SSH command injection detected: %(command)s") -class CoraidException(CinderException): +class QoSSpecsExists(Duplicate): + message = _("QoS Specs %(specs_id)s already exists.") + + +class QoSSpecsCreateFailed(CinderException): + message = _("Failed to create qos_specs: " + "%(name)s with specs %(qos_specs)s.") + + +class QoSSpecsUpdateFailed(CinderException): + message = _("Failed to update qos_specs: " + "%(specs_id)s with specs %(qos_specs)s.") + + +class QoSSpecsNotFound(NotFound): + message = _("No such QoS spec %(specs_id)s.") + + +class QoSSpecsAssociateFailed(CinderException): + message = _("Failed to associate qos_specs: " + "%(specs_id)s with type %(type_id)s.") + + +class QoSSpecsDisassociateFailed(CinderException): + message = _("Failed to disassociate qos_specs: " + "%(specs_id)s with type %(type_id)s.") + + +class QoSSpecsKeyNotFound(NotFound): + message = _("QoS spec %(specs_id)s has no spec with " + "key %(specs_key)s.") + + +class InvalidQoSSpecs(Invalid): + message = _("Invalid qos specs: %(reason)s") + + +class QoSSpecsInUse(CinderException): + message = _("QoS Specs %(specs_id)s is still associated with entities.") + + +class KeyManagerError(CinderException): + msg_fmt = _("key manager error: %(reason)s") + + +# Driver specific exceptions +# Coraid +class CoraidException(VolumeDriverException): message = _('Coraid Cinder Driver exception.') @@ -600,46 +594,83 @@ class CoraidESMNotAvailable(CoraidException): message = _('Coraid ESM not available with reason: %(reason)s.') -class QoSSpecsExists(Duplicate): - message = _("QoS Specs %(specs_id)s already exists.") +# Zadara +class ZadaraException(VolumeDriverException): + message = _('Zadara Cinder Driver exception.') -class QoSSpecsCreateFailed(CinderException): - message = _("Failed to create qos_specs: " - "%(name)s with specs %(qos_specs)s.") +class ZadaraServerCreateFailure(ZadaraException): + message = _("Unable to create server object for initiator %(name)s") -class QoSSpecsUpdateFailed(CinderException): - message = _("Failed to update qos_specs: " - "%(specs_id)s with specs %(qos_specs)s.") +class ZadaraServerNotFound(ZadaraException): + message = _("Unable to find server object for initiator %(name)s") -class QoSSpecsNotFound(NotFound): - message = _("No such QoS spec %(specs_id)s.") +class ZadaraVPSANoActiveController(ZadaraException): + message = _("Unable to find any active VPSA controller") -class QoSSpecsAssociateFailed(CinderException): - message = _("Failed to associate qos_specs: " - "%(specs_id)s with type %(type_id)s.") +class ZadaraAttachmentsNotFound(ZadaraException): + message = _("Failed to retrieve attachments for volume %(name)s") -class QoSSpecsDisassociateFailed(CinderException): - message = _("Failed to disassociate qos_specs: " - "%(specs_id)s with type %(type_id)s.") +class ZadaraInvalidAttachmentInfo(ZadaraException): + message = _("Invalid attachment info for volume %(name)s: %(reason)s") -class QoSSpecsKeyNotFound(NotFound): - message = _("QoS spec %(specs_id)s has no spec with " - "key %(specs_key)s.") +class BadHTTPResponseStatus(ZadaraException): + message = _("Bad HTTP response status %(status)s") -class InvalidQoSSpecs(Invalid): - message = _("Invalid qos specs: %(reason)s") +#SolidFire +class SolidFireAPIException(VolumeBackendAPIException): + message = _("Bad response from SolidFire API") -class QoSSpecsInUse(CinderException): - message = _("QoS Specs %(specs_id)s is still associated with entities.") +class SolidFireDriverException(VolumeDriverException): + message = _("SolidFire Cinder Driver exception") -class KeyManagerError(CinderException): - msg_fmt = _("key manager error: %(reason)s") +class SolidFireAPIDataException(SolidFireAPIException): + message = _("Error in SolidFire API response: data=%(data)s") + + +class SolidFireAccountNotFound(SolidFireDriverException): + message = _("Unable to locate account %(account_name)s on " + "Solidfire device") + + +class DuplicateSolidFireVolumeNames(SolidFireDriverException): + message = _("Detected more than one volume with name %(vol_name)s") + + +# HP 3Par +class Invalid3PARDomain(VolumeDriverException): + message = _("Invalid 3PAR Domain: %(err)s") + + +# NFS driver +class NfsException(VolumeDriverException): + message = _("Unknown NFS exception") + + +class NfsNoSharesMounted(VolumeDriverException): + message = _("No mounted NFS shares found") + + +class NfsNoSuitableShareFound(VolumeDriverException): + message = _("There is no share which can host %(volume_size)sG") + + +# Gluster driver +class GlusterfsException(VolumeDriverException): + message = _("Unknown Gluster exception") + + +class GlusterfsNoSharesMounted(VolumeDriverException): + message = _("No mounted Gluster shares found") + + +class GlusterfsNoSuitableShareFound(VolumeDriverException): + message = _("There is no share which can host %(volume_size)sG") diff --git a/cinder/tests/test_glusterfs.py b/cinder/tests/test_glusterfs.py index af4e1201e..58822be04 100644 --- a/cinder/tests/test_glusterfs.py +++ b/cinder/tests/test_glusterfs.py @@ -405,7 +405,8 @@ class GlusterFsDriverTestCase(test.TestCase): drv._mounted_shares = [] - self.assertRaises(exception.NotFound, drv._find_share, + self.assertRaises(exception.GlusterfsNoSharesMounted, + drv._find_share, self.TEST_SIZE_IN_GB) def test_find_share(self): diff --git a/cinder/tests/test_nfs.py b/cinder/tests/test_nfs.py index 7ce00e1b3..54aba6d22 100644 --- a/cinder/tests/test_nfs.py +++ b/cinder/tests/test_nfs.py @@ -399,7 +399,7 @@ class NfsDriverTestCase(test.TestCase): drv._mounted_shares = [] - self.assertRaises(exception.NotFound, drv._find_share, + self.assertRaises(exception.NfsNoSharesMounted, drv._find_share, self.TEST_SIZE_IN_GB) def test_find_share(self): diff --git a/cinder/tests/test_solidfire.py b/cinder/tests/test_solidfire.py index 73e11793f..b22850988 100644 --- a/cinder/tests/test_solidfire.py +++ b/cinder/tests/test_solidfire.py @@ -367,7 +367,7 @@ class SolidFireVolumeTestCase(test.TestCase): 'created_at': timeutils.utcnow()} sfv = SolidFireDriver(configuration=self.configuration) - self.assertRaises(exception.SfAccountNotFound, + self.assertRaises(exception.SolidFireAccountNotFound, sfv.delete_volume, testvol) @@ -426,6 +426,6 @@ class SolidFireVolumeTestCase(test.TestCase): 'created_at': timeutils.utcnow()} sfv = SolidFireDriver(configuration=self.configuration) - self.assertRaises(exception.SfAccountNotFound, + self.assertRaises(exception.SolidFireAccountNotFound, sfv.extend_volume, testvol, 2) diff --git a/cinder/volume/drivers/solidfire.py b/cinder/volume/drivers/solidfire.py index c82a01fdb..d86204862 100644 --- a/cinder/volume/drivers/solidfire.py +++ b/cinder/volume/drivers/solidfire.py @@ -231,7 +231,8 @@ class SolidFireDriver(SanISCSIDriver): sf_account_name = self._get_sf_account_name(project_id) sfaccount = self._get_sfaccount_by_name(sf_account_name) if sfaccount is None: - raise exception.SfAccountNotFound(account_name=sf_account_name) + raise exception.SolidFireAccountNotFound( + account_name=sf_account_name) return sfaccount -- 2.45.2