diff --git a/Makefile b/Makefile index ae003a0622711469931895a7d0d33f08d4005909..975867db2627a78057d779ce6c47202a2b1335a5 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # are defined in the RULES file. TOP = . -SUBDIRS = src +SUBDIRS = src doc .PHONY: support dev-config .PHONY: db backup deploy-web-portal undeploy-web-portal deploy-ds-web-service undeploy-ds-web-service deploy-daq-web-service undeploy-daq-web-service deploy-cat-web-service undeploy-cat-web-service deploy-proc-web-service undeploy-proc-web-service @@ -30,6 +30,9 @@ destroy-db: backup: $(TOP)/sbin/dm_backup.sh +api-doc: + make -C doc/sphinx html + configure-web-portal: dist $(TOP)/sbin/dm_configure_web_portal.sh diff --git a/src/python/dm/common/api/dmApi.py b/src/python/dm/common/api/dmApi.py index 4c6f46212e8a0a049da43b91a0fc666232b4d87f..9de12e9d557c83878c1d836a96911ba9ca374ba1 100755 --- a/src/python/dm/common/api/dmApi.py +++ b/src/python/dm/common/api/dmApi.py @@ -1,6 +1,8 @@ #!/usr/bin/env python import json +from functools import wraps +from decorator import decorator from dm.common.exceptions.dmException import DmException from dm.common.utility.loggingManager import LoggingManager @@ -34,3 +36,25 @@ class DmApi(object): cls.getLogger().exception('%s' % ex) raise DmException(exception=ex) return decorate + + # Exception decorator for api calls + # Use two decorators for the sake of documentation + @classmethod + def execute2(cls, *dargs, **dkwargs): + def internalCall(func): + @wraps(func) + def wrappedCall(func, *args, **kwargs): + try: + response = func(*args, **kwargs) + return response + except DmException, ex: + raise + except Exception, ex: + cls.getLogger().exception('%s' % ex) + raise DmException(exception=ex) + return decorator(wrappedCall, func) + if len(dargs) == 1 and callable(dargs[0]): + return internalCall(dargs[0]) + else: + return internalCall + diff --git a/src/python/dm/daq_web_service/api/experimentRestApi.py b/src/python/dm/daq_web_service/api/experimentDaqApi.py similarity index 66% rename from src/python/dm/daq_web_service/api/experimentRestApi.py rename to src/python/dm/daq_web_service/api/experimentDaqApi.py index 817c81e1b40c05f1d3e9fbfaabd81eb270f31a5f..b9b9f9ccb30d6cb43de77d66baa7c405e8a023f9 100755 --- a/src/python/dm/daq_web_service/api/experimentRestApi.py +++ b/src/python/dm/daq_web_service/api/experimentDaqApi.py @@ -13,13 +13,61 @@ from dm.common.objects.pluginInfo import PluginInfo from dm.common.objects.daqInfo import DaqInfo from daqRestApi import DaqRestApi -class ExperimentRestApi(DaqRestApi): +class ExperimentDaqApi(DaqRestApi): + ''' + This class is used to access experiment interface provided by the + DAQ service on a DM experiment station. + ''' def __init__(self, username=None, password=None, host=None, port=None, protocol=None): + ''' + Constructor. + + :param username: DM username + :type username: str + + :param password: DM password + :type password: str + + :param host: DM service host + :type host: str + + :param port: DM service port + :type port: int + + :param protocol: DM service protocol + :type protocol: str + + >>> api = ExperimentDaqApi(username='dm', password='XYZ', host='bluegill1', port=22236, protocol='https') + ''' DaqRestApi.__init__(self, username, password, host, port, protocol) - @DaqRestApi.execute + @DaqRestApi.execute2 def startDaq(self, experimentName, dataDirectory, daqInfo={}): + ''' + Start data acquisition (real-time directory monitoring and file upload). + + :param experimentName: experiment name + :type experimentName: str + + :param dataDirectory: data directory URL + :type dataDirectory: str + + :param daqInfo: DAQ info + :type dataDirectory: dict + + :returns: DAQ id + + :raises InvalidRequest: in case of empty experiment name or data directory + + :raises AuthorizationError: in case user is not authorized to manage DM station + + :raises ObjectNotFound: in case experiment does not exist + + :raises DmException: in case of any other errors + + >>> daqId = api.startDaq(experimentName='test01', dataDirectory='/home/dm/test') + ''' if not experimentName: raise InvalidRequest('Experiment name must be provided.') if not dataDirectory: @@ -29,8 +77,27 @@ class ExperimentRestApi(DaqRestApi): responseDict = self.sendSessionRequest(url=url, method='POST') return DaqInfo(responseDict) - @DaqRestApi.execute + @DaqRestApi.execute2 def stopDaq(self, experimentName, dataDirectory): + ''' + Stop data acquisition (real-time directory monitoring and file upload). + + :param experimentName: experiment name + :type experimentName: str + + :param dataDirectory: data directory URL + :type dataDirectory: str + + :raises InvalidRequest: in case of empty experiment name or data directory + + :raises AuthorizationError: in case user is not authorized to manage DM station + + :raises ObjectNotFound: in case experiment does not exist, or if there are no active DAQs for a given experiment and data directory + + :raises DmException: in case of any other errors + + >>> api.stopDaq(experimentName='test01', dataDirectory='/home/dm/test') + ''' if not experimentName: raise InvalidRequest('Experiment name must be provided.') if not dataDirectory: @@ -100,6 +167,6 @@ class ExperimentRestApi(DaqRestApi): # Testing. if __name__ == '__main__': - api = ExperimentRestApi('sveseli', 'sveseli', 'zagreb.svdev.net', 33336, 'http') + api = ExperimentDaqApi('sveseli', 'sveseli', 'zagreb.svdev.net', 33336, 'http') print api.startDaq('experiment1', '/tmp/data/experiment1') diff --git a/src/python/dm/daq_web_service/cli/getDaqInfoCli.py b/src/python/dm/daq_web_service/cli/getDaqInfoCli.py index 4361c6d2d1b14bea25400fb7baf9b318dfdbb119..7a9bb5d245464f93e3aa6bc3395834b83d320b52 100755 --- a/src/python/dm/daq_web_service/cli/getDaqInfoCli.py +++ b/src/python/dm/daq_web_service/cli/getDaqInfoCli.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from daqWebServiceSessionCli import DaqWebServiceSessionCli -from dm.daq_web_service.api.experimentRestApi import ExperimentRestApi +from dm.daq_web_service.api.experimentDaqApi import ExperimentDaqApi from dm.common.exceptions.invalidRequest import InvalidRequest class GetDaqInfoCli(DaqWebServiceSessionCli): @@ -24,7 +24,7 @@ Description: Retrieves detailed information for the specified data acquisition. """) self.checkArgs() - api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) + api = ExperimentDaqApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) daqInfo = api.getDaqInfo(self.getId()) print daqInfo.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat()) diff --git a/src/python/dm/daq_web_service/cli/getProcessingPluginsCli.py b/src/python/dm/daq_web_service/cli/getProcessingPluginsCli.py index 07afe11daf5d42a883a1f75f1e92b72c43e1547c..42b41ab41e7b3509c1a900187c17af77be6aa616 100755 --- a/src/python/dm/daq_web_service/cli/getProcessingPluginsCli.py +++ b/src/python/dm/daq_web_service/cli/getProcessingPluginsCli.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from dm.daq_web_service.api.experimentRestApi import ExperimentRestApi +from dm.daq_web_service.api.experimentDaqApi import ExperimentDaqApi from daqWebServiceSessionCli import DaqWebServiceSessionCli class GetProcessingPluginsCli(DaqWebServiceSessionCli): @@ -14,7 +14,7 @@ class GetProcessingPluginsCli(DaqWebServiceSessionCli): Description: Retrieves list of known processing plugins. """) - api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) + api = ExperimentDaqApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) plugins = api.getProcessingPlugins() for plugin in plugins: print plugin.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat()) diff --git a/src/python/dm/daq_web_service/cli/getUploadInfoCli.py b/src/python/dm/daq_web_service/cli/getUploadInfoCli.py index ca3a4a294e973cea9c1d26faac19d84c6638093d..7764ff98d43254c403444f336980b26caa721936 100755 --- a/src/python/dm/daq_web_service/cli/getUploadInfoCli.py +++ b/src/python/dm/daq_web_service/cli/getUploadInfoCli.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from daqWebServiceSessionCli import DaqWebServiceSessionCli -from dm.daq_web_service.api.experimentRestApi import ExperimentRestApi +from dm.daq_web_service.api.experimentDaqApi import ExperimentDaqApi from dm.common.exceptions.invalidRequest import InvalidRequest class GetUploadInfoCli(DaqWebServiceSessionCli): @@ -24,7 +24,7 @@ Description: Retrieves detailed information for the specified data upload id. """) self.checkArgs() - api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) + api = ExperimentDaqApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) uploadInfo = api.getUploadInfo(self.getId()) print uploadInfo.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat()) diff --git a/src/python/dm/daq_web_service/cli/listDaqsCli.py b/src/python/dm/daq_web_service/cli/listDaqsCli.py index 1e7a7232761b299c0166682f23fae9e49f3e86fc..e3a18de0f5374718398443162d447d151650149b 100755 --- a/src/python/dm/daq_web_service/cli/listDaqsCli.py +++ b/src/python/dm/daq_web_service/cli/listDaqsCli.py @@ -3,7 +3,7 @@ from daqWebServiceSessionCli import DaqWebServiceSessionCli from dm.common.constants import dmProcessingStatus -from dm.daq_web_service.api.experimentRestApi import ExperimentRestApi +from dm.daq_web_service.api.experimentDaqApi import ExperimentDaqApi from dm.common.exceptions.invalidRequest import InvalidRequest class ListDaqsCli(DaqWebServiceSessionCli): @@ -27,7 +27,7 @@ Description: Retrieves all known daqs. """) self.checkArgs() - api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) + api = ExperimentDaqApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) daqs = api.listDaqs(self.getStatus()) for daq in daqs: print daq.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat()) diff --git a/src/python/dm/daq_web_service/cli/listUploadsCli.py b/src/python/dm/daq_web_service/cli/listUploadsCli.py index 8cc30c5065bf109f97eb20dee597259a185e6de1..451025ef6fa05b7616f56920d5e5aa66462f6707 100755 --- a/src/python/dm/daq_web_service/cli/listUploadsCli.py +++ b/src/python/dm/daq_web_service/cli/listUploadsCli.py @@ -3,7 +3,7 @@ from daqWebServiceSessionCli import DaqWebServiceSessionCli from dm.common.constants import dmProcessingStatus -from dm.daq_web_service.api.experimentRestApi import ExperimentRestApi +from dm.daq_web_service.api.experimentDaqApi import ExperimentDaqApi from dm.common.exceptions.invalidRequest import InvalidRequest class ListUploadsCli(DaqWebServiceSessionCli): @@ -27,7 +27,7 @@ Description: Retrieves all known uploads. """) self.checkArgs() - api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) + api = ExperimentDaqApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) uploads = api.listUploads(self.getStatus()) for upload in uploads: print upload.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat()) diff --git a/src/python/dm/daq_web_service/cli/startDaqCli.py b/src/python/dm/daq_web_service/cli/startDaqCli.py index 7570f412c498416c7f6327ee41dac5da0b0ca608..9bbf662d86688d2432c4a9dc0ec153df106063d3 100755 --- a/src/python/dm/daq_web_service/cli/startDaqCli.py +++ b/src/python/dm/daq_web_service/cli/startDaqCli.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from dm.daq_web_service.api.experimentRestApi import ExperimentRestApi +from dm.daq_web_service.api.experimentDaqApi import ExperimentDaqApi from dm.common.exceptions.invalidRequest import InvalidRequest from daqWebServiceSessionCli import DaqWebServiceSessionCli @@ -33,7 +33,7 @@ Description: file processing plugins. """) self.checkArgs() - api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) + api = ExperimentDaqApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) daqInfo = self.splitArgsIntoDict() self.updateDaqInfoFromOptions(daqInfo) daqInfo = api.startDaq(self.getExperimentName(), self.getDataDirectory(), daqInfo=daqInfo) diff --git a/src/python/dm/daq_web_service/cli/stopDaqCli.py b/src/python/dm/daq_web_service/cli/stopDaqCli.py index 98bf9d7248a538974328232f7e22c95288205f8a..0c956a05c094b5d1e8d1abc1eddf158da6177c25 100755 --- a/src/python/dm/daq_web_service/cli/stopDaqCli.py +++ b/src/python/dm/daq_web_service/cli/stopDaqCli.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from dm.daq_web_service.api.experimentRestApi import ExperimentRestApi +from dm.daq_web_service.api.experimentDaqApi import ExperimentDaqApi from dm.common.exceptions.invalidRequest import InvalidRequest from daqWebServiceSessionCli import DaqWebServiceSessionCli @@ -24,7 +24,7 @@ Description: Stop DAQ for a given experiment and data directory. """) self.checkArgs() - api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) + api = ExperimentDaqApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) daqInfo = api.stopDaq(self.getExperimentName(), self.getDataDirectory()) print daqInfo.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat()) diff --git a/src/python/dm/daq_web_service/cli/stopUploadCli.py b/src/python/dm/daq_web_service/cli/stopUploadCli.py index c153555384b77b2f90e555abd74ca05edc6fe466..df0019254702149fc3becc6bdb1dec019fea119f 100755 --- a/src/python/dm/daq_web_service/cli/stopUploadCli.py +++ b/src/python/dm/daq_web_service/cli/stopUploadCli.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from daqWebServiceSessionCli import DaqWebServiceSessionCli -from dm.daq_web_service.api.experimentRestApi import ExperimentRestApi +from dm.daq_web_service.api.experimentDaqApi import ExperimentDaqApi from dm.common.exceptions.invalidRequest import InvalidRequest class StopUploadCli(DaqWebServiceSessionCli): @@ -24,7 +24,7 @@ Description: Aborts specified data upload. """) self.checkArgs() - api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) + api = ExperimentDaqApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) uploadInfo = api.stopUpload(self.getId()) print uploadInfo.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat()) diff --git a/src/python/dm/daq_web_service/cli/uploadCli.py b/src/python/dm/daq_web_service/cli/uploadCli.py index f578309d336ff912763306e85b519b0c33bf5872..9185ff10676f0fb15e734de5b75a31a8daed12dd 100755 --- a/src/python/dm/daq_web_service/cli/uploadCli.py +++ b/src/python/dm/daq_web_service/cli/uploadCli.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from daqWebServiceSessionCli import DaqWebServiceSessionCli -from dm.daq_web_service.api.experimentRestApi import ExperimentRestApi +from dm.daq_web_service.api.experimentDaqApi import ExperimentDaqApi from dm.common.exceptions.invalidRequest import InvalidRequest from dm.common.constants import dmProcessingMode @@ -49,7 +49,7 @@ Description: to file processing plugins. """) self.checkArgs() - api = ExperimentRestApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) + api = ExperimentDaqApi(self.getLoginUsername(), self.getLoginPassword(), self.getServiceHost(), self.getServicePort(), self.getServiceProtocol()) daqInfo = self.splitArgsIntoDict() self.updateDaqInfoFromOptions(daqInfo) uploadInfo = api.upload(self.getExperimentName(), self.getDataDirectory(), daqInfo=daqInfo)