Skip to content

Commit fa3a5b9

Browse files
authored
Merge pull request #18 from pndaproject/PNDA-2499
Return all exceptions to API caller
2 parents fa046b9 + 437489a commit fa3a5b9

File tree

5 files changed

+37
-61
lines changed

5 files changed

+37
-61
lines changed

api/src/main/resources/app.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ def finish():
8383
self.finish(ex.msg)
8484
else:
8585
self.set_status(500)
86-
self.finish()
86+
if "information" in str(ex):
87+
msg = str(ex)
88+
else:
89+
msg = {"status": "UNKNOWN", "information": str(ex)}
90+
self.finish(msg)
8791

8892
IOLoop.instance().add_callback(callback=finish)
8993

api/src/main/resources/deployment_manager.py

Lines changed: 21 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import requests
3131

3232
import application_creator
33-
from exceptiondef import ConflictingState, NotFound, ExceptionThatShouldBeDisplayedToCaller
33+
from exceptiondef import ConflictingState, NotFound
3434
from package_parser import PackageParser
3535
from async_dispatcher import AsyncDispatcher
3636
from lifecycle_states import ApplicationState, PackageDeploymentState
@@ -151,7 +151,6 @@ def deploy_package(self, package):
151151
# this function will be executed in the background:
152152
def _do_deploy():
153153
# if this value is not changed, then it is assumed that the operation never completed
154-
deploy_status = {"state": PackageDeploymentState.NOTDEPLOYED, "information": "Error deploying " + package}
155154
try:
156155
package_file = package + '.tar.gz'
157156
logging.info("deploy: %s", package)
@@ -165,12 +164,9 @@ def _do_deploy():
165164
deploy_status = {"state": PackageDeploymentState.DEPLOYED,
166165
"information": "Deployed " + package + " at " + self.utc_string()}
167166
logging.info("deployed: %s", package)
168-
except ExceptionThatShouldBeDisplayedToCaller as ex:
169-
# log error to screen:
170-
logging.error(ex.msg)
171-
# prepare human readable message
172-
error_message = package + " " + str(type(ex).__name__) + ", details: " + json.dumps(ex.msg)
173-
# set the status:
167+
except Exception as ex:
168+
logging.error(str(ex))
169+
error_message = "Error deploying " + package + " " + str(type(ex).__name__) + ", details: " + json.dumps(str(ex))
174170
deploy_status = {"state": PackageDeploymentState.NOTDEPLOYED, "information": error_message}
175171
raise
176172
finally:
@@ -190,26 +186,21 @@ def utc_string(self):
190186
def undeploy_package(self, package):
191187
# this function will be executed in the background:
192188
def do_undeploy():
193-
undeploy_failed = True
194-
# this will be the default error message if it is not clear what the error was:
195-
deploy_status = {"state": PackageDeploymentState.DEPLOYED, "information": "Error undeploying " + package}
189+
deploy_status = None
196190
try:
197-
198191
logging.info("undeploy: %s", package)
199192
self._package_registrar.delete_package(package)
200193
logging.info("undeployed: %s", package)
201-
deploy_status = None
202-
undeploy_failed = False
203-
except ExceptionThatShouldBeDisplayedToCaller as ex:
194+
except Exception as ex:
204195
# log error to screen:
205-
logging.error(ex.msg)
196+
logging.error(str(ex))
206197
# prepare human readable message
207-
error_message = package + " " + str(type(ex).__name__) + ", details: " + json.dumps(ex.msg)
198+
error_message = "Error undeploying " + package + " " + str(type(ex).__name__) + ", details: " + json.dumps(str(ex))
208199
# set the status:
209-
deploy_status = {"state": PackageDeploymentState.NOTDEPLOYED, "information": error_message}
200+
deploy_status = {"state": PackageDeploymentState.DEPLOYED, "information": error_message}
210201
raise
211202
finally:
212-
if undeploy_failed:
203+
if deploy_status is not None:
213204
# persist any errors in the database, but still throw them:
214205
self._package_registrar.set_package_deploy_status(package, deploy_status)
215206

@@ -303,15 +294,9 @@ def do_work():
303294
create_data = self._application_registrar.get_create_data(application)
304295
self._application_creator.start_application(application, create_data)
305296
self._application_registrar.set_application_status(application, ApplicationState.STARTED)
306-
except ExceptionThatShouldBeDisplayedToCaller as ex:
307-
self._handle_application_error(application, ex, ApplicationState.CREATED)
308-
raise
309297
except Exception as ex:
310-
# report the error:
311-
self._application_registrar.set_application_status(application, ApplicationState.CREATED,
312-
"Error starting application: " + application)
313-
# re-throw the exception after reporting it
314-
raise Exception(ex)
298+
self._handle_application_error(application, ex, ApplicationState.CREATED, "starting")
299+
raise
315300
finally:
316301
self._clear_package_progress(application)
317302
self._state_change_event_application(application)
@@ -331,15 +316,9 @@ def do_work():
331316
create_data = self._application_registrar.get_create_data(application)
332317
self._application_creator.stop_application(application, create_data)
333318
self._application_registrar.set_application_status(application, ApplicationState.CREATED)
334-
except ExceptionThatShouldBeDisplayedToCaller as ex:
335-
self._handle_application_error(application, ex, ApplicationState.STARTED)
336-
raise
337319
except Exception as ex:
338-
# report the error:
339-
self._application_registrar.set_application_status(application, ApplicationState.STARTED,
340-
"Error stopping application: " + application)
341-
# re-throw the exception after reporting it
342-
raise Exception(ex)
320+
self._handle_application_error(application, ex, ApplicationState.STARTED, "stopping")
321+
raise
343322
finally:
344323
self._clear_package_progress(application)
345324
self._state_change_event_application(application)
@@ -388,14 +367,10 @@ def do_work():
388367
package_data_path, package_metadata, application, overrides)
389368
self._application_registrar.set_create_data(application, create_data)
390369
self._application_registrar.set_application_status(application, ApplicationState.CREATED)
391-
except ExceptionThatShouldBeDisplayedToCaller as ex:
392-
self._handle_application_error(application, ex, ApplicationState.NOTCREATED)
393-
raise
394370
except Exception as ex:
395-
self._application_registrar.set_application_status(application, ApplicationState.NOTCREATED,
396-
"Error creating application: " + application)
371+
self._handle_application_error(application, ex, ApplicationState.NOTCREATED, "creating")
397372
logging.error(traceback.format_exc(ex))
398-
raise ex
373+
raise
399374
finally:
400375
# clear inner locks:
401376
self._clear_package_progress(application)
@@ -404,7 +379,7 @@ def do_work():
404379

405380
self.dispatcher.run_as_asynch(task=do_work)
406381

407-
def _handle_application_error(self, application, ex, app_status):
382+
def _handle_application_error(self, application, ex, app_status, operation):
408383
"""
409384
Use to handle application exceptions which should be relayed back to the user
410385
Sets the application state to an error
@@ -413,9 +388,9 @@ def _handle_application_error(self, application, ex, app_status):
413388
:param app_status: The status the app should be at following the error.
414389
"""
415390
# log error to screen:
416-
logging.error(ex.msg)
391+
logging.error(str(ex))
417392
# prepare human readable message
418-
error_message = application + " " + str(type(ex).__name__) + ", details: " + json.dumps(ex.msg)
393+
error_message = "Error %s " % operation + application + " " + str(type(ex).__name__) + ", details: " + json.dumps(str(ex))
419394
# set the status:
420395
self._application_registrar.set_application_status(application, app_status, error_message)
421396

@@ -432,15 +407,9 @@ def do_work():
432407
create_data = self._application_registrar.get_create_data(application)
433408
self._application_creator.destroy_application(application, create_data)
434409
self._application_registrar.delete_application(application)
435-
except ExceptionThatShouldBeDisplayedToCaller as ex:
436-
self._handle_application_error(application, ex, ApplicationState.STARTED)
437-
raise
438410
except Exception as ex:
439-
# report the error:
440-
self._application_registrar.set_application_status(application, ApplicationState.STARTED,
441-
"Error deleting application: " + application)
442-
# re-throw the exception after reporting it
443-
raise Exception(ex)
411+
self._handle_application_error(application, ex, ApplicationState.STARTED, "deleting")
412+
raise
444413
finally:
445414
self._clear_package_progress(application)
446415
self._state_change_event_application(application)

api/src/main/resources/exceptiondef.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,39 @@
2020
either express or implied.
2121
"""
2222

23-
class ExceptionThatShouldBeDisplayedToCaller(Exception):
23+
class DmException(Exception):
2424
"""
2525
Any exception derived from this class should be exposed through the API to the caller.
2626
"""
2727
def __init__(self, arg):
28-
super(ExceptionThatShouldBeDisplayedToCaller, self).__init__(arg)
28+
super(DmException, self).__init__(arg)
2929
self.msg = arg
3030

31-
class NotFound(ExceptionThatShouldBeDisplayedToCaller):
31+
def __str__(self):
32+
return str(self.msg)
33+
34+
class NotFound(DmException):
3235

3336
def __init__(self, arg):
3437
super(NotFound, self).__init__(arg)
3538
self.msg = arg
3639

3740

38-
class ConflictingState(ExceptionThatShouldBeDisplayedToCaller):
41+
class ConflictingState(DmException):
3942

4043
def __init__(self, arg):
4144
super(ConflictingState, self).__init__(arg)
4245
self.msg = arg
4346

4447

45-
class FailedValidation(ExceptionThatShouldBeDisplayedToCaller):
48+
class FailedValidation(DmException):
4649

4750
def __init__(self, arg):
4851
super(FailedValidation, self).__init__(arg)
4952
self.msg = arg
5053

5154

52-
class FailedCreation(ExceptionThatShouldBeDisplayedToCaller):
55+
class FailedCreation(DmException):
5356

5457
def __init__(self, arg):
5558
super(FailedCreation, self).__init__(arg)

api/src/main/resources/test_application_registrar.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
import unittest
2525
from mock import patch
26-
import happybase
26+
import happybase # pylint: disable=unused-import
2727
from Hbase_thrift import AlreadyExists
2828
from application_registrar import HbaseApplicationRegistrar
2929
from lifecycle_states import ApplicationState

api/src/main/resources/test_package_registrar.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
import unittest
2525
import json
26-
import happybase
26+
import happybase # pylint: disable=unused-import
2727
from mock import patch, mock_open, Mock
2828
from Hbase_thrift import AlreadyExists
2929
from package_registrar import HbasePackageRegistrar

0 commit comments

Comments
 (0)