diff options
author | Steve Baker <sbaker@redhat.com> | 2020-01-22 14:43:56 +1300 |
---|---|---|
committer | Steve Baker <sbaker@redhat.com> | 2020-01-22 16:46:59 +1300 |
commit | f192f2c45d5d89f64159a20d0dc8c7d743885ece (patch) | |
tree | 4d19b572b64e307b5fc09e521d4a1f0bae216090 | |
parent | cc7a9c29c21627b8d605113988fc3227bf29b253 (diff) | |
download | ironic-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.py | 30 | ||||
-rw-r--r-- | ironic/api/controllers/v1/port.py | 4 | ||||
-rw-r--r-- | ironic/api/controllers/v1/portgroup.py | 8 | ||||
-rw-r--r-- | ironic/api/controllers/v1/types.py | 6 | ||||
-rw-r--r-- | ironic/api/controllers/v1/utils.py | 26 | ||||
-rw-r--r-- | ironic/common/exception.py | 5 | ||||
-rw-r--r-- | ironic/tests/unit/api/controllers/v1/test_utils.py | 40 |
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') |