Replace ApiError with new exceptions

* Convert ApiError to EC2APIError
* Add new exceptions to replace ApiError where it didn't belong
* Fixes bug 926250

Change-Id: Ia711440ee0313faf8ea8c87e2c0a2f5b39cc55a2
This commit is contained in:
Brian Waldon
2012-02-03 13:29:57 -08:00
parent b800ceb90e
commit ad0648d9fe
11 changed files with 74 additions and 51 deletions

View File

@@ -1607,7 +1607,7 @@ class VsaDriveTypeCommands(object):
"""Marks volume types as deleted"""
try:
volume_types.destroy(self.context, name)
except exception.ApiError:
except exception.InvalidVolumeType:
print "Valid volume type name is required"
sys.exit(1)
except exception.DBError, e:
@@ -1786,7 +1786,7 @@ class InstanceTypeCommands(object):
"""Marks instance types / flavors as deleted"""
try:
instance_types.destroy(name)
except exception.ApiError:
except exception.InstanceTypeNotFound:
print "Valid instance type name is required"
sys.exit(1)
except exception.DBError, e:

View File

@@ -80,7 +80,7 @@ class Error(Exception):
super(Error, self).__init__(message)
class ApiError(Error):
class EC2APIError(Error):
def __init__(self, message='Unknown', code=None):
self.msg = message
self.code = code
@@ -88,7 +88,7 @@ class ApiError(Error):
outstr = '%s: %s' % (code, message)
else:
outstr = '%s' % message
super(ApiError, self).__init__(outstr)
super(EC2APIError, self).__init__(outstr)
class DBError(Error):
@@ -223,6 +223,14 @@ class Invalid(NovaException):
message = _("Unacceptable parameters.")
class InvalidSnapshot(Invalid):
message = _("Invalid snapshot") + ": %(reason)s"
class VolumeUnattached(Invalid):
message = _("Volume %(volume_id)s is not attached to anything")
class InvalidKeypair(Invalid):
message = _("Keypair data is invalid")
@@ -248,7 +256,11 @@ class InvalidInstanceType(Invalid):
class InvalidVolumeType(Invalid):
message = _("Invalid volume type %(volume_type)s.")
message = _("Invalid volume type") + ": %(reason)s"
class InvalidVolume(Invalid):
message = _("Invalid volume") + ": %(reason)s"
class InvalidPortRange(Invalid):
@@ -930,9 +942,8 @@ class WillNotSchedule(NovaException):
message = _("Host %(host)s is not up or doesn't exist.")
class QuotaError(ApiError):
"""Quota Exceeded."""
pass
class QuotaError(NovaException):
message = _("Quota exceeded") + ": code=%(code)s"
class AggregateNotFound(NotFound):
@@ -962,3 +973,24 @@ class AggregateHostExists(Duplicate):
class DuplicateSfVolumeNames(Duplicate):
message = _("Detected more than one volume with name %(vol_name)")
class VolumeTypeCreateFailed(NovaException):
message = _("Cannot create volume_type with "
"name %(name)s and specs %(extra_specs)s")
class InstanceTypeCreateFailed(NovaException):
message = _("Unable to create instance type")
class SolidFireAPIException(NovaException):
message = _("Bad response from SolidFire API")
class SolidFireAPIStatusException(SolidFireAPIException):
message = _("Error in SolidFire API response: status=%(status)s")
class SolidFireAPIDataException(SolidFireAPIException):
message = _("Error in SolidFire API response: data=%(data)s")

View File

@@ -13,14 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from nova import context
from nova import db
from nova import exception
from nova import flags
from nova import log as logging
from nova import rpc
from nova.scheduler import vsa as vsa_sched
from nova import test
from nova.tests.scheduler import test_scheduler
from nova import utils
from nova.volume import volume_types

View File

@@ -176,5 +176,5 @@ class SolidFireVolumeTestCase(test.TestCase):
def test_get_cluster_info_fail(self):
SFID._issue_api_request = self.fake_issue_api_request_fails
sfv = SFID()
self.assertRaises(exception.ApiError,
self.assertRaises(exception.SolidFireAPIException,
sfv._get_cluster_info)

View File

@@ -2357,7 +2357,7 @@ class ComputeAPITestCase(BaseTestCase):
address = '0.1.2.3'
self.compute.run_instance(self.context, instance_uuid)
self.assertRaises(exception.ApiError,
self.assertRaises(exception.FixedIpNotFoundForInstance,
self.compute_api.associate_floating_ip,
self.context,
instance,
@@ -2967,7 +2967,7 @@ class ComputeAPITestCase(BaseTestCase):
self.compute_api.delete(self.context, instance)
def test_attach_volume_invalid(self):
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InvalidDevicePath,
self.compute_api.attach_volume,
self.context,
None,

View File

@@ -85,7 +85,7 @@ class InstanceTypeTestCase(test.TestCase):
'instance type was not created')
instance_types.destroy(name)
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InstanceTypeNotFound,
instance_types.get_instance_type, inst_type_id)
# deleted instance should not be in list anymoer
@@ -133,7 +133,7 @@ class InstanceTypeTestCase(test.TestCase):
'unknown_flavor')
def test_duplicate_names_fail(self):
"""Ensures that name duplicates raise ApiError"""
"""Ensures that name duplicates raise InstanceTypeCreateFailed"""
name = 'some_name'
instance_types.create(name, 256, 1, 120, 200, 'flavor1')
self.assertRaises(exception.InstanceTypeExists,
@@ -141,7 +141,7 @@ class InstanceTypeTestCase(test.TestCase):
name, 256, 1, 120, 200, 'flavor2')
def test_duplicate_flavorids_fail(self):
"""Ensures that flavorid duplicates raise ApiError"""
"""Ensures that flavorid duplicates raise InstanceTypeCreateFailed"""
flavorid = 'flavor1'
instance_types.create('name one', 256, 1, 120, 200, flavorid)
self.assertRaises(exception.InstanceTypeExists,
@@ -156,7 +156,7 @@ class InstanceTypeTestCase(test.TestCase):
def test_will_not_get_bad_default_instance_type(self):
"""ensures error raised on bad default instance type"""
self.flags(default_instance_type='unknown_flavor')
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InstanceTypeNotFound,
instance_types.get_default_instance_type)
def test_will_get_instance_type_by_id(self):
@@ -167,12 +167,12 @@ class InstanceTypeTestCase(test.TestCase):
def test_will_not_get_instance_type_by_unknown_id(self):
"""Ensure get by name returns default flavor with no name"""
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InstanceTypeNotFound,
instance_types.get_instance_type, 10000)
def test_will_not_get_instance_type_with_bad_id(self):
"""Ensure get by name returns default flavor with bad name"""
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InstanceTypeNotFound,
instance_types.get_instance_type, 'asdf')
def test_instance_type_get_by_None_name_returns_default(self):
@@ -183,7 +183,7 @@ class InstanceTypeTestCase(test.TestCase):
def test_will_not_get_instance_type_with_bad_name(self):
"""Ensure get by name returns default flavor with bad name"""
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InstanceTypeNotFound,
instance_types.get_instance_type_by_name, 10000)
def test_will_not_get_instance_by_unknown_flavor_id(self):

View File

@@ -249,7 +249,7 @@ class VolumeTestCase(test.TestCase):
volume_api = nova.volume.api.API()
volume = volume_api.get(self.context, volume['id'])
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InvalidVolume,
volume_api.create_snapshot,
self.context, volume,
'fake_name', 'fake_description')

View File

@@ -85,7 +85,7 @@ class VolumeTypeTestCase(test.TestCase):
def test_non_existant_vol_type_shouldnt_delete(self):
"""Ensures that volume type creation fails with invalid args"""
self.assertRaises(exception.ApiError,
self.assertRaises(exception.VolumeTypeNotFoundByName,
volume_types.destroy, self.ctxt, "sfsfsdfdfs")
def test_repeated_vol_types_shouldnt_raise(self):

View File

@@ -90,7 +90,7 @@ class VsaTestCase(test.TestCase):
def test_vsa_create_wrong_image_name(self):
param = {'image_name': 'wrong_image_name'}
self.assertRaises(exception.ApiError,
self.assertRaises(exception.ImageNotFound,
self.vsa_api.create, self.context, **param)
def test_vsa_create_db_error(self):
@@ -100,19 +100,19 @@ class VsaTestCase(test.TestCase):
raise exception.Error
self.stubs.Set(nova.db, 'vsa_create', fake_vsa_create)
self.assertRaises(exception.ApiError,
self.assertRaises(exception.Error,
self.vsa_api.create, self.context)
def test_vsa_create_wrong_storage_params(self):
vsa_list1 = self.vsa_api.get_all(self.context)
param = {'storage': [{'stub': 1}]}
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InvalidVolumeType,
self.vsa_api.create, self.context, **param)
vsa_list2 = self.vsa_api.get_all(self.context)
self.assertEqual(len(vsa_list2), len(vsa_list1))
param = {'storage': [{'drive_name': 'wrong name'}]}
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InvalidVolumeType,
self.vsa_api.create, self.context, **param)
def test_vsa_create_with_storage(self, multi_vol_creation=True):

View File

@@ -107,14 +107,14 @@ class VsaVolumesTestCase(test.TestCase):
'deleting')
def test_vsa_volume_delete_nonavail_volume(self):
""" Check volume deleton in different states. """
""" Check volume deletion in different states. """
volume_param = self._default_volume_param()
volume_ref = self.volume_api.create(self.context, **volume_param)
self.volume_api.update(self.context,
volume_ref,
{'status': 'in-use'})
self.assertRaises(exception.ApiError,
self.assertRaises(exception.InvalidVolume,
self.volume_api.delete,
self.context, volume_ref)

View File

@@ -23,8 +23,6 @@ For assistance and guidelines pls contact
Zadara Storage Inc & Openstack community
"""
import sys
from nova import compute
from nova import exception
from nova import flags
@@ -81,8 +79,8 @@ class API(base.Base):
vol_type['extra_specs'].get('drive_type') is None or
vol_type['extra_specs'].get('drive_size') is None):
raise exception.ApiError(_("Invalid drive type %s")
% vol_type['name'])
msg = _("invalid drive data")
raise exception.InvalidVolumeType(reason=msg)
def _get_default_vsa_instance_type(self):
return instance_types.get_instance_type_by_name(
@@ -104,13 +102,14 @@ class API(base.Base):
num_disks = node.get('num_drives', 1)
if name is None:
raise exception.ApiError(_("No drive_name param found in %s")
% node)
msg = _("drive_name not defined")
raise exception.InvalidVolumeType(reason=msg)
try:
vol_type = volume_types.get_volume_type_by_name(context, name)
except exception.NotFound:
raise exception.ApiError(_("Invalid drive type name %s")
% name)
msg = _("invalid drive type name %s")
raise exception.InvalidVolumeType(reason=msg % name)
self._check_volume_type_correctness(vol_type)
@@ -177,13 +176,10 @@ class API(base.Base):
# check if image is ready before starting any work
if image_name is None:
image_name = FLAGS.vc_image_name
try:
image_service = self.compute_api.image_service
vc_image = image_service.show_by_name(context, image_name)
vc_image_href = vc_image['id']
except exception.ImageNotFound:
raise exception.ApiError(_("Failed to find configured image %s")
% image_name)
options = {
'display_name': display_name,
@@ -198,10 +194,8 @@ class API(base.Base):
LOG.info(_("Creating VSA: %s") % options)
# create DB entry for VSA instance
try:
vsa_ref = self.db.vsa_create(context, options)
except exception.Error:
raise exception.ApiError(_(sys.exc_info()[1]))
vsa_id = vsa_ref['id']
vsa_name = vsa_ref['name']
@@ -209,10 +203,9 @@ class API(base.Base):
try:
volume_params = self._check_storage_parameters(context, vsa_name,
storage, shared)
except exception.ApiError:
except exception.InvalidVolumeType:
self.db.vsa_destroy(context, vsa_id)
raise exception.ApiError(_("Error in storage parameters: %s")
% storage)
raise
# after creating DB entry, re-check and set some defaults
updates = {}
@@ -358,7 +351,7 @@ class API(base.Base):
LOG.info(_("VSA ID %(vsa_id)s: Deleting %(direction)s "
"volume %(vol_name)s"), locals())
self.volume_api.delete(context, volume)
except exception.ApiError:
except exception.InvalidVolume:
LOG.info(_("Unable to delete volume %s"), volume['name'])
if force_delete:
LOG.info(_("VSA ID %(vsa_id)s: Forced delete. "