summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Baker <sbaker@redhat.com>2020-01-22 14:43:56 +1300
committerSteve Baker <sbaker@redhat.com>2020-01-22 16:46:59 +1300
commitf192f2c45d5d89f64159a20d0dc8c7d743885ece (patch)
tree4d19b572b64e307b5fc09e521d4a1f0bae216090
parentcc7a9c29c21627b8d605113988fc3227bf29b253 (diff)
downloadironic-f192f2c45d5d89f64159a20d0dc8c7d743885ece.tar.gz
Subclass wsme.exc.ClientSideError
This change avoids importing a wsgi namespace exception class, and allows the future option of changing the parent class of exception.ClientSideError when wsme is no longer processing API requests. Change-Id: I8165e094fafb91ff94eaa1dd96baba7671487448 Story: 1651346
-rw-r--r--ironic/api/controllers/v1/node.py30
-rw-r--r--ironic/api/controllers/v1/port.py4
-rw-r--r--ironic/api/controllers/v1/portgroup.py8
-rw-r--r--ironic/api/controllers/v1/types.py6
-rw-r--r--ironic/api/controllers/v1/utils.py26
-rw-r--r--ironic/common/exception.py5
-rw-r--r--ironic/tests/unit/api/controllers/v1/test_utils.py40
7 files changed, 62 insertions, 57 deletions
diff --git a/ironic/api/controllers/v1/node.py b/ironic/api/controllers/v1/node.py
index c72a7bbde..d2454bab1 100644
--- a/ironic/api/controllers/v1/node.py
+++ b/ironic/api/controllers/v1/node.py
@@ -564,7 +564,7 @@ class NodeStatesController(rest.RestController):
msg = (_('A non-empty "rescue_password" is required when '
'setting target provision state to %s') %
ir_states.VERBS['rescue'])
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
api.request.rpcapi.do_node_rescue(
api.request.context, rpc_node.uuid, rescue_password, topic)
@@ -578,7 +578,7 @@ class NodeStatesController(rest.RestController):
if not clean_steps:
msg = (_('"clean_steps" is required when setting target '
'provision state to %s') % ir_states.VERBS['clean'])
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
_check_clean_steps(clean_steps)
api.request.rpcapi.do_node_clean(
@@ -678,14 +678,14 @@ class NodeStatesController(rest.RestController):
if clean_steps and target != ir_states.VERBS['clean']:
msg = (_('"clean_steps" is only valid when setting target '
'provision state to %s') % ir_states.VERBS['clean'])
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
if (rescue_password is not None
and target != ir_states.VERBS['rescue']):
msg = (_('"rescue_password" is only valid when setting target '
'provision state to %s') % ir_states.VERBS['rescue'])
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
if (rpc_node.provision_state == ir_states.INSPECTWAIT and
@@ -1700,10 +1700,10 @@ class NodesController(rest.RestController):
This function will raise an exception for unacceptable names.
:param names: list of node names to check
- :param error_msg: error message in case of wsme.exc.ClientSideError,
+ :param error_msg: error message in case of exception.ClientSideError,
should contain %(name)s placeholder.
:raises: exception.NotAcceptable
- :raises: wsme.exc.ClientSideError
+ :raises: exception.ClientSideError
"""
if not api_utils.allow_node_logical_names():
raise exception.NotAcceptable()
@@ -1711,11 +1711,11 @@ class NodesController(rest.RestController):
reserved_names = get_nodes_controller_reserved_names()
for name in names:
if not api_utils.is_valid_node_name(name):
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
error_msg % {'name': name},
status_code=http_client.BAD_REQUEST)
if name in reserved_names:
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
'The word "%(name)s" is reserved and can not be used as a '
'node name. Reserved words are: %(reserved)s.' %
{'name': name,
@@ -1762,11 +1762,11 @@ class NodesController(rest.RestController):
:param rpc_node: RPC Node object to be verified.
:param node_ident: the UUID or logical name of a node.
- :raises: wsme.exc.ClientSideError
+ :raises: exception.ClientSideError
"""
delta = rpc_node.obj_what_changed()
if 'driver' in delta and rpc_node.console_enabled:
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
_("Node %s can not update the driver while the console is "
"enabled. Please stop the console first.") % node_ident,
status_code=http_client.CONFLICT)
@@ -2107,15 +2107,15 @@ class NodesController(rest.RestController):
not in ir_states.UPDATE_ALLOWED_STATES):
msg = _("Node %s can not be updated while a state transition "
"is in progress.")
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg % node_ident, status_code=http_client.CONFLICT)
elif (rpc_node.provision_state == ir_states.INSPECTING
and api_utils.allow_inspect_wait_state()):
msg = _('Cannot update node "%(node)s" while it is in state '
'"%(state)s".') % {'node': rpc_node.uuid,
'state': ir_states.INSPECTING}
- raise wsme.exc.ClientSideError(msg,
- status_code=http_client.CONFLICT)
+ raise exception.ClientSideError(msg,
+ status_code=http_client.CONFLICT)
elif api_utils.get_patch_values(patch, '/owner'):
# check if updating a provisioned node's owner is allowed
@@ -2129,7 +2129,7 @@ class NodesController(rest.RestController):
'is in state "%(state)s".') % {
'node': rpc_node.uuid,
'state': ir_states.ACTIVE}
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.CONFLICT)
# check if node has an associated allocation with an owner
@@ -2142,7 +2142,7 @@ class NodesController(rest.RestController):
msg = _('Cannot update owner of node "%(node)s" while '
'it is allocated to an allocation with an '
' owner.') % {'node': rpc_node.uuid}
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.CONFLICT)
except exception.AllocationNotFound:
pass
diff --git a/ironic/api/controllers/v1/port.py b/ironic/api/controllers/v1/port.py
index e2c845d57..9e551894f 100644
--- a/ironic/api/controllers/v1/port.py
+++ b/ironic/api/controllers/v1/port.py
@@ -715,8 +715,8 @@ class PortsController(rest.RestController):
'in state "%(state)s".') % {'port': rpc_port.uuid,
'node': rpc_node.uuid,
'state': ir_states.INSPECTING}
- raise wsme.exc.ClientSideError(msg,
- status_code=http_client.CONFLICT)
+ raise exception.ClientSideError(msg,
+ status_code=http_client.CONFLICT)
notify_extra = {'node_uuid': rpc_node.uuid,
'portgroup_uuid': port.portgroup_uuid}
diff --git a/ironic/api/controllers/v1/portgroup.py b/ironic/api/controllers/v1/portgroup.py
index 3f6df9e1d..464dcf59e 100644
--- a/ironic/api/controllers/v1/portgroup.py
+++ b/ironic/api/controllers/v1/portgroup.py
@@ -484,7 +484,7 @@ class PortgroupsController(pecan.rest.RestController):
and not api_utils.is_valid_logical_name(portgroup.name)):
error_msg = _("Cannot create portgroup with invalid name "
"'%(name)s'") % {'name': portgroup.name}
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
error_msg, status_code=http_client.BAD_REQUEST)
pg_dict = portgroup.as_dict()
@@ -544,7 +544,7 @@ class PortgroupsController(pecan.rest.RestController):
" invalid name '%(name)s'") % {'portgroup':
portgroup_ident,
'name': name}
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
error_msg, status_code=http_client.BAD_REQUEST)
portgroup_dict = rpc_portgroup.as_dict()
@@ -578,8 +578,8 @@ class PortgroupsController(pecan.rest.RestController):
'"%(node)s" while it is in state "%(state)s".') % {
'portgroup': rpc_portgroup.uuid, 'node': rpc_node.uuid,
'state': ir_states.INSPECTING}
- raise wsme.exc.ClientSideError(msg,
- status_code=http_client.CONFLICT)
+ raise exception.ClientSideError(msg,
+ status_code=http_client.CONFLICT)
notify.emit_start_notification(context, rpc_portgroup, 'update',
node_uuid=rpc_node.uuid)
diff --git a/ironic/api/controllers/v1/types.py b/ironic/api/controllers/v1/types.py
index 07b59819a..6df548a46 100644
--- a/ironic/api/controllers/v1/types.py
+++ b/ironic/api/controllers/v1/types.py
@@ -246,16 +246,16 @@ class JsonPatchType(wtypes.Base):
_path = '/' + patch.path.split('/')[1]
if _path in patch.internal_attrs():
msg = _("'%s' is an internal attribute and can not be updated")
- raise wsme.exc.ClientSideError(msg % patch.path)
+ raise exception.ClientSideError(msg % patch.path)
if patch.path in patch.non_removable_attrs() and patch.op == 'remove':
msg = _("'%s' is a mandatory attribute and can not be removed")
- raise wsme.exc.ClientSideError(msg % patch.path)
+ raise exception.ClientSideError(msg % patch.path)
if patch.op != 'remove':
if patch.value is wsme.Unset:
msg = _("'add' and 'replace' operations need a value")
- raise wsme.exc.ClientSideError(msg)
+ raise exception.ClientSideError(msg)
ret = {'path': patch.path, 'op': patch.op}
if patch.value is not wsme.Unset:
diff --git a/ironic/api/controllers/v1/utils.py b/ironic/api/controllers/v1/utils.py
index fc6d00a9d..7712fc30f 100644
--- a/ironic/api/controllers/v1/utils.py
+++ b/ironic/api/controllers/v1/utils.py
@@ -82,21 +82,21 @@ def validate_limit(limit):
return CONF.api.max_limit
if limit <= 0:
- raise wsme.exc.ClientSideError(_("Limit must be positive"))
+ raise exception.ClientSideError(_("Limit must be positive"))
return min(CONF.api.max_limit, limit)
def validate_sort_dir(sort_dir):
if sort_dir not in ['asc', 'desc']:
- raise wsme.exc.ClientSideError(_("Invalid sort direction: %s. "
- "Acceptable values are "
- "'asc' or 'desc'") % sort_dir)
+ raise exception.ClientSideError(_("Invalid sort direction: %s. "
+ "Acceptable values are "
+ "'asc' or 'desc'") % sort_dir)
return sort_dir
def validate_trait(trait, error_prefix=_('Invalid trait')):
- error = wsme.exc.ClientSideError(
+ error = exception.ClientSideError(
_('%(error_prefix)s. A valid trait must be no longer than 255 '
'characters. Standard traits are defined in the os_traits library. '
'A custom trait must start with the prefix CUSTOM_ and use '
@@ -125,7 +125,7 @@ def apply_jsonpatch(doc, patch):
:param patch: The JSON patch to apply.
:returns: The result of the patch operation.
:raises: PatchError if the patch fails to apply.
- :raises: wsme.exc.ClientSideError if the patch adds a new root attribute.
+ :raises: exception.ClientSideError if the patch adds a new root attribute.
"""
# Prevent removal of root attributes.
for p in patch:
@@ -133,7 +133,7 @@ def apply_jsonpatch(doc, patch):
if p['path'].lstrip('/') not in doc:
msg = _('Adding a new attribute (%s) to the root of '
'the resource is not allowed')
- raise wsme.exc.ClientSideError(msg % p['path'])
+ raise exception.ClientSideError(msg % p['path'])
# Apply operations one at a time, to improve error reporting.
for patch_op in patch:
@@ -403,7 +403,7 @@ def vendor_passthru(ident, method, topic, data=None, driver_passthru=False):
"""
if not method:
- raise wsme.exc.ClientSideError(_("Method not specified"))
+ raise exception.ClientSideError(_("Method not specified"))
if data is None:
data = {}
@@ -638,14 +638,14 @@ def check_allow_configdrive(target, configdrive=None):
if target not in allowed_targets:
msg = (_('Adding a config drive is only supported when setting '
'provision state to %s') % ', '.join(allowed_targets))
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
try:
jsonschema.validate(configdrive, _CONFIG_DRIVE_SCHEMA)
except json_schema_exc.ValidationError as e:
msg = _('Invalid configdrive format: %s') % e
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
if isinstance(configdrive, dict):
@@ -654,7 +654,7 @@ def check_allow_configdrive(target, configdrive=None):
' starting with API version %(base)s.%(opr)s') % {
'base': versions.BASE_VERSION,
'opr': versions.MINOR_56_BUILD_CONFIGDRIVE}
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
if ('vendor_data' in configdrive and
not allow_configdrive_vendor_data()):
@@ -662,7 +662,7 @@ def check_allow_configdrive(target, configdrive=None):
' starting with API version %(base)s.%(opr)s') % {
'base': versions.BASE_VERSION,
'opr': versions.MINOR_59_CONFIGDRIVE_VENDOR_DATA}
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
@@ -682,7 +682,7 @@ def check_allow_filter_by_fault(fault):
msg = (_('Unrecognized fault "%(fault)s" is specified, allowed faults '
'are %(valid_faults)s') %
{'fault': fault, 'valid_faults': faults.VALID_FAULTS})
- raise wsme.exc.ClientSideError(
+ raise exception.ClientSideError(
msg, status_code=http_client.BAD_REQUEST)
diff --git a/ironic/common/exception.py b/ironic/common/exception.py
index 1d100f832..1daee6318 100644
--- a/ironic/common/exception.py
+++ b/ironic/common/exception.py
@@ -20,6 +20,7 @@ from http import client as http_client
from ironic_lib.exception import IronicException
from oslo_log import log as logging
+import wsme
from ironic.common.i18n import _
@@ -705,3 +706,7 @@ class IBMCError(DriverOperationError):
class IBMCConnectionError(IBMCError):
_msg_fmt = _("IBMC connection failed for node %(node)s: %(error)s")
+
+
+class ClientSideError(wsme.exc.ClientSideError):
+ pass
diff --git a/ironic/tests/unit/api/controllers/v1/test_utils.py b/ironic/tests/unit/api/controllers/v1/test_utils.py
index 3f25469d1..80f74936d 100644
--- a/ironic/tests/unit/api/controllers/v1/test_utils.py
+++ b/ironic/tests/unit/api/controllers/v1/test_utils.py
@@ -47,17 +47,17 @@ class TestApiUtils(base.TestCase):
self.assertEqual(CONF.api.max_limit, limit)
# negative
- self.assertRaises(wsme.exc.ClientSideError, utils.validate_limit, -1)
+ self.assertRaises(exception.ClientSideError, utils.validate_limit, -1)
# zero
- self.assertRaises(wsme.exc.ClientSideError, utils.validate_limit, 0)
+ self.assertRaises(exception.ClientSideError, utils.validate_limit, 0)
def test_validate_sort_dir(self):
sort_dir = utils.validate_sort_dir('asc')
self.assertEqual('asc', sort_dir)
# invalid sort_dir parameter
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.validate_sort_dir,
'fake-sort')
@@ -65,25 +65,25 @@ class TestApiUtils(base.TestCase):
utils.validate_trait(os_traits.HW_CPU_X86_AVX2)
utils.validate_trait("CUSTOM_1")
utils.validate_trait("CUSTOM_TRAIT_GOLD")
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.validate_trait, "A" * 256)
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.validate_trait, "CuSTOM_1")
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.validate_trait, "")
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.validate_trait, "CUSTOM_bob")
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.validate_trait, "CUSTOM_1-BOB")
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.validate_trait, "aCUSTOM_1a")
large = "CUSTOM_" + ("1" * 248)
self.assertEqual(255, len(large))
utils.validate_trait(large)
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.validate_trait, large + "1")
# Check custom error prefix.
- self.assertRaisesRegex(wsme.exc.ClientSideError,
+ self.assertRaisesRegex(exception.ClientSideError,
"spongebob",
utils.validate_trait, "invalid", "spongebob")
@@ -97,7 +97,7 @@ class TestApiUtils(base.TestCase):
def test_apply_jsonpatch_no_add_root_attr(self):
doc = {}
patch = [{"op": "add", "path": "/foo", "value": 42}]
- self.assertRaisesRegex(wsme.exc.ClientSideError,
+ self.assertRaisesRegex(exception.ClientSideError,
"Adding a new attribute",
utils.apply_jsonpatch, doc, patch)
@@ -488,14 +488,14 @@ class TestCheckAllowFields(base.TestCase):
def test_check_allow_configdrive_fails(self, mock_request):
mock_request.version.minor = 35
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.check_allow_configdrive, states.DELETED,
"abcd")
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.check_allow_configdrive, states.ACTIVE,
{'meta_data': {}})
mock_request.version.minor = 34
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.check_allow_configdrive, states.REBUILD,
"abcd")
@@ -518,7 +518,7 @@ class TestCheckAllowFields(base.TestCase):
def test_check_allow_configdrive_vendor_data_failed(self, mock_request):
mock_request.version.minor = 58
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.check_allow_configdrive,
states.ACTIVE,
{'meta_data': {},
@@ -528,15 +528,15 @@ class TestCheckAllowFields(base.TestCase):
def test_check_allow_configdrive_as_dict_invalid(self, mock_request):
mock_request.version.minor = 59
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.check_allow_configdrive, states.REBUILD,
{'foo': 'bar'})
for key in ['meta_data', 'network_data']:
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.check_allow_configdrive, states.REBUILD,
{key: 'a string'})
for key in ['meta_data', 'network_data', 'user_data']:
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.check_allow_configdrive, states.REBUILD,
{key: 42})
@@ -654,7 +654,7 @@ class TestNodeIdent(base.TestCase):
class TestVendorPassthru(base.TestCase):
def test_method_not_specified(self):
- self.assertRaises(wsme.exc.ClientSideError,
+ self.assertRaises(exception.ClientSideError,
utils.vendor_passthru, 'fake-ident',
None, 'fake-topic', data='fake-data')