Steps to reproduce - creating node with duplicate uuid:
1. Create the first node specifying some uuid
curl -i -X POST -H 'X-Auth-Token: <your token>'Content-Type: application/json' -H 'Accept: application/json' -H -d '{"driver": "fake", "uuid": "2359bca1-3ca1-4913-92c2-4d40438e01e5"}' http://192.168.122.224:6385/v1/nodesHTTP/1.0
2. Create the second node specifying the same uuid. Response will be
{"error_message": "{\"debuginfo\": null, \"faultcode\": \"Server\", \"faultstring\": \"(IntegrityError) (1062, \\\"Duplicate entry '2359bca1-3ca1-4913-92c2-4d40438e01e5' for key 'node_uuid_ux'\\\") 'INSERT INTO nodes (created_at, updated_at, uuid, instance_uuid, chassis_id, power_state, target_power_state, provision_state, target_provision_state, last_error, properties, driver, driver_info, reservation, maintenance, extra) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)' (datetime.datetime(2014, 2, 7, 15, 14, 12, 730006), None, '2359bca1-3ca1-4913-92c2-4d40438e01e5', None, None, None, None, None, None, None, '\\\"{}\\\"', 'fake', '\\\"{}\\\"', None, 0, '\\\"{}\\\"')\"}"}
Response code 500, which should be 409
The hook intended to cut exception traceback cannot handle this.
https://github.com/openstack/ironic/blob/master/ironic/api/hooks.py#L139-L141
Because fault string in this case is not a traceback and does not contain python traceback artifacts.
We need either convert all such DB exceptions to IronicException, or create one more hook. The first one is more preferable to me.
So part of the issue is that the exception being raised by node.save() is a generic ironic. openstack. common. db.exception. DBError, rather than DBDuplicateEntry.
The other part is that while we have debug on, we probably still want the error messages, right?
I think the solution is going to be wrapping all the .save() methods in try/excepts in sqlalchemy/api (where this is happening), and raising an IronicException with a message based on whether debug is on or not. Some of the .save() calls catch some instances, but I think it should be catching the broader DBError to avoid leaking details. For example, if a DBConnectionError pops up in a call with only DuplicateError caught, it may leak some details as well.