From acfae547b251d19062b1741468fb15dfece4bd3d Mon Sep 17 00:00:00 2001 From: Cristiano Urban Date: Fri, 24 Sep 2021 17:16:06 +0200 Subject: [PATCH] Added 'search' method to 'vos_job' command. Signed-off-by: Cristiano Urban --- client/config/bash_completion/vos_job | 4 +-- client/vos_job | 26 +++++++++++++++ transfer_service/db_connector.py | 47 +++++++++++++++++++++++++++ transfer_service/job_rpc_server.py | 14 ++++++++ 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/client/config/bash_completion/vos_job b/client/config/bash_completion/vos_job index b2719f9..deee9bd 100644 --- a/client/config/bash_completion/vos_job +++ b/client/config/bash_completion/vos_job @@ -10,9 +10,9 @@ _vos_job() COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" - opts="info list results" + opts="info list search results" - if [[ ${cur} == info || ${cur} == results || ${COMP_CWORD} -eq 1 ]] ; then + if [[ ${cur} == info || ${cur} == search || ${cur} == results || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 fi diff --git a/client/vos_job b/client/vos_job index ba0777e..e83198b 100644 --- a/client/vos_job +++ b/client/vos_job @@ -71,6 +71,24 @@ class VOSJob(RedisRPCClient): sys.exit(f"\nError code: {errorCode}\nError message: {errorMsg}\n") else: sys.exit("\nFATAL: Unknown response type.\n") + + def search(self, searchStr): + jobRequest = { "requestType": "JOB_SEARCH", "searchStr": searchStr } + jobResponse = self.call(jobRequest) + if "responseType" not in jobResponse: + sys.exit("FATAL: Malformed response.\n") + elif jobResponse["responseType"] == "SEARCH_DONE": + jobSearch = jobResponse["jobSearch"] + if jobSearch: + print("\n" + tabulate(jobResponse["jobSearch"], headers = "keys", tablefmt = "pretty") + "\n") + else: + sys.exit(f"\nThe search did not return any results.\n") + elif jobResponse["responseType"] == "ERROR": + errorCode = jobResponse["errorCode"] + errorMsg = jobResponse["errorMsg"] + sys.exit(f"\nError code: {errorCode}\nError message: {errorMsg}\n") + else: + sys.exit("\nFATAL: Unknown response type.\n") def results(self, jobId): jobRequest = { "requestType": "JOB_RESULTS", "jobId": jobId } @@ -116,6 +134,12 @@ DESCRIPTION info prints a JSON object containing the job info according to the UWS specification. A job ID is required as argument. + + search + performs a search on jobs and returns those having a match between the search string + passed by the user and one of the following fields: + + 'job_id', 'job_type', 'ownder_id', 'user_name' results prints a JSON object containing the job results according to the UWS specification. @@ -141,6 +165,8 @@ elif len(sys.argv) == 3: vosJobCli.help() elif cmd == "info": vosJobCli.info(arg) + elif cmd == "search": + vosJobCli.search(arg) elif cmd == "results": vosJobCli.results(arg) else: diff --git a/transfer_service/db_connector.py b/transfer_service/db_connector.py index c4b373e..b63e7e1 100644 --- a/transfer_service/db_connector.py +++ b/transfer_service/db_connector.py @@ -508,6 +508,53 @@ class DbConnector(object): return result finally: self.connPool.putconn(conn, close = False) + + def searchJobs(self, searchStr): + "Performs a search on jobs." + conn = self.getConnection() + try: + cursor = conn.cursor(cursor_factory = RealDictCursor) + cursor.execute(""" + SELECT job_id, + job_type, + phase, + start_time, + end_time, + owner_id + FROM job + JOIN users + ON job.owner_id = users.user_id + WHERE job_type IN ('pullFromVoSpace', + 'pullToVoSpace', + 'pushToVoSpace', + 'vos_data', + 'vos_group', + 'vos_import') + AND (job_id ~ %s + OR job_type ~ %s + OR owner_id ~ %s + OR user_name ~ %s) + ORDER BY creation_time DESC; + """, + (searchStr, + searchStr, + searchStr, + searchStr,)) + result = cursor.fetchall() + cursor.close() + except Exception: + if not conn.closed: + conn.rollback() + raise + else: + for row in result: + for idx in row: + el = row[idx] + if isinstance(el, datetime.datetime): + row[idx] = el.isoformat() + return result + finally: + self.connPool.putconn(conn, close = False) ##### User ##### diff --git a/transfer_service/job_rpc_server.py b/transfer_service/job_rpc_server.py index 124d2ef..2352338 100644 --- a/transfer_service/job_rpc_server.py +++ b/transfer_service/job_rpc_server.py @@ -113,6 +113,20 @@ class JobRPCServer(RedisRPCServer): "errorCode": 2, "errorMsg": errorMsg } return response + elif requestBody["requestType"] == "JOB_SEARCH": + searchStr = requestBody["searchStr"] + try: + result = self.dbConn.searchJobs(searchStr) + except Exception: + errorMsg = "Database error." + self.logger.exception(errorMsg) + response = { "responseType": "ERROR", + "errorCode": 2, + "errorMsg": errorMsg } + return response + else: + response = { "responseType": "SEARCH_DONE", + "jobSearch": result } else: errorMsg = "Unkown request type." self.logger.error(errorMsg) -- GitLab