diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a8414e32dfbf872096c9769d5350744d8dce433..0f51a45141eb4bd2f4dc14b0fcb856114cfcf642 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # CHANGELOG +### Pre-release v4.0.0b7 - Release date: 2024-05-14 + +* Reduced writing time in status updater background task +* Improved documentation +* Removed `listexp` view +* Minor fixes + ### Pre-release v4.0.0b6 - Release date: 2024-04-19 * Added filter by autosubmit version in `/v4/experiments` diff --git a/autosubmit_api/__init__.py b/autosubmit_api/__init__.py index e7eae9a30091fe0cf2d717b94857d259a82c4e09..2eeabb72a6e3aa7797442fbd31b95425370317ca 100644 --- a/autosubmit_api/__init__.py +++ b/autosubmit_api/__init__.py @@ -17,6 +17,6 @@ # You should have received a copy of the GNU General Public License # along with Autosubmit. If not, see . -__version__ = "4.0.0b6" +__version__ = "4.0.0b7" __author__ = "Luiggi Tenorio, Bruno P. Kinoshita, Cristian GutiƩrrez, Julian Berlin, Wilmer Uruchi" __credits__ = "Barcelona Supercomputing Center" \ No newline at end of file diff --git a/autosubmit_api/bgtasks/tasks/status_updater.py b/autosubmit_api/bgtasks/tasks/status_updater.py index 186be6fccb18c783a2c3c9079d9389a66b3b23c8..971cd1f14c7eea3a43228c8fb5c9d362878a858b 100644 --- a/autosubmit_api/bgtasks/tasks/status_updater.py +++ b/autosubmit_api/bgtasks/tasks/status_updater.py @@ -1,7 +1,7 @@ from datetime import datetime import os import time -from typing import List +from typing import Dict, List from sqlalchemy import select from autosubmit_api.bgtasks.bgtask import BackgroundTaskTemplate @@ -50,6 +50,15 @@ class StatusUpdater(BackgroundTaskTemplate): query_result = conn.execute(tables.experiment_table.select()).all() return [ExperimentModel.model_validate(row._mapping) for row in query_result] + @classmethod + def _get_current_status(cls) -> Dict[str, str]: + """ + Get the current status of the experiments + """ + with create_as_times_db_engine().connect() as conn: + query_result = conn.execute(tables.experiment_status_table.select()).all() + return {row.name: row.status for row in query_result} + @classmethod def _check_exp_running(cls, expid: str) -> bool: """ @@ -113,7 +122,20 @@ class StatusUpdater(BackgroundTaskTemplate): # Read experiments table exp_list = cls._get_experiments() + # Read current status of all experiments + current_status = cls._get_current_status() + # Check every experiment status & update for experiment in exp_list: is_running = cls._check_exp_running(experiment.name) - cls._update_experiment_status(experiment, is_running) + new_status = ( + RunningStatus.RUNNING if is_running else RunningStatus.NOT_RUNNING + ) + if ( + current_status.get(experiment.name, RunningStatus.NOT_RUNNING) + != new_status + ): + cls.logger.info( + f"[{cls.id}] Updating status of {experiment.name} to {new_status}" + ) + cls._update_experiment_status(experiment, is_running) diff --git a/autosubmit_api/database/common.py b/autosubmit_api/database/common.py index 6891df5403feed41ba4a06ac72b50a3cd10274a7..defe7056fce0dd39124123d138f33849032eea0a 100644 --- a/autosubmit_api/database/common.py +++ b/autosubmit_api/database/common.py @@ -1,6 +1,15 @@ import os from typing import Any -from sqlalchemy import Connection, Engine, Select, create_engine, select, text, func +from sqlalchemy import ( + Connection, + Engine, + NullPool, + Select, + create_engine, + select, + text, + func, +) from autosubmit_api.builders import BaseBuilder from autosubmit_api.logger import logger from autosubmit_api.config.basicConfig import APIBasicConfig @@ -14,7 +23,7 @@ class AttachedDatabaseConnBuilder(BaseBuilder): def __init__(self) -> None: super().__init__(False) APIBasicConfig.read() - self.engine = create_engine("sqlite://") + self.engine = create_engine("sqlite://", poolclass=NullPool) self._product = self.engine.connect() def attach_db(self, path: str, name: str): @@ -51,7 +60,9 @@ def create_autosubmit_db_engine() -> Engine: Create an engine for the autosubmit DDBB. Usually named autosubmit.db """ APIBasicConfig.read() - return create_engine(f"sqlite:///{ os.path.abspath(APIBasicConfig.DB_PATH)}") + return create_engine( + f"sqlite:///{ os.path.abspath(APIBasicConfig.DB_PATH)}", poolclass=NullPool + ) def create_as_times_db_engine() -> Engine: @@ -60,7 +71,7 @@ def create_as_times_db_engine() -> Engine: """ APIBasicConfig.read() db_path = os.path.join(APIBasicConfig.DB_DIR, APIBasicConfig.AS_TIMES_DB) - return create_engine(f"sqlite:///{ os.path.abspath(db_path)}") + return create_engine(f"sqlite:///{ os.path.abspath(db_path)}", poolclass=NullPool) def execute_with_limit_offset( diff --git a/autosubmit_api/database/db_common.py b/autosubmit_api/database/db_common.py index 40443b2afee46b7e2bf9ce4d59ab20b45b3b719b..6eec21ad01cca983e74344c65c9afb7cebffaf44 100644 --- a/autosubmit_api/database/db_common.py +++ b/autosubmit_api/database/db_common.py @@ -205,10 +205,10 @@ def search_experiment_by_id(query, exp_type=None, only_active=None, owner=None): 'Connection to database could not be established: {0}', e.message) return False if owner: - query = "SELECT id,name,user,created,model,branch,hpc,description FROM listexp WHERE user='{0}'".format(owner) + query = "SELECT id,name,user,created,model,branch,hpc,description FROM experiment e left join details d on e.id = d.exp_id WHERE user='{0}'".format(owner) # print(query) else: - query = "SELECT id,name,user,created,model,branch,hpc,description FROM listexp WHERE (name LIKE '" + query + \ + query = "SELECT id,name,user,created,model,branch,hpc,description FROM experiment e left join details d on e.id = d.exp_id WHERE (name LIKE '" + query + \ "%' OR description LIKE '%" + query + \ "%' OR user LIKE '%" + query + "%')" if exp_type and len(exp_type) > 0: @@ -302,7 +302,7 @@ def get_current_running_exp(): Log.error( 'Connection to database could not be established: {0}', e.message) return False - query = "SELECT id,name,user,created,model,branch,hpc,description FROM listexp" + query = "SELECT id,name,user,created,model,branch,hpc,description FROM experiment e left join details d on e.id = d.exp_id" APIBasicConfig.read() # print(query) cursor.execute(query) diff --git a/autosubmit_api/experiment/common_db_requests.py b/autosubmit_api/experiment/common_db_requests.py index 187cd45f8aa8f4771383588c2f2fa25da2cd4c47..e8aa22fa4e2add6edad197839a2becf0a0287401 100644 --- a/autosubmit_api/experiment/common_db_requests.py +++ b/autosubmit_api/experiment/common_db_requests.py @@ -110,9 +110,10 @@ def get_specific_experiment_status(expid): tables.experiment_status_table.c.name == expid ) ).one_or_none() + if row: + return (row.name, row.status) except Exception as exc: logger.error(f"Exception while reading experiment_status for {expid}: {exc}") logger.error(traceback.format_exc()) - if row: - return (row.name, row.status) + return (expid, "NOT RUNNING") diff --git a/autosubmit_api/experiment/common_requests.py b/autosubmit_api/experiment/common_requests.py index f5a909502217aadfac338d06a6cd857b949a4262..f730d58d0fafc31c8523d10a09201e8a41a1bb2c 100644 --- a/autosubmit_api/experiment/common_requests.py +++ b/autosubmit_api/experiment/common_requests.py @@ -59,7 +59,7 @@ from autosubmit_api.builders.experiment_history_builder import ExperimentHistory from autosubmit_api.builders.configuration_facade_builder import ConfigurationFacadeDirector, AutosubmitConfigurationFacadeBuilder from autosubmit_api.builders.joblist_loader_builder import JobListLoaderBuilder, JobListLoaderDirector from autosubmit_api.components.jobs.job_support import JobSupport -from typing import Dict, Any, Optional +from typing import Dict, Any, Optional, Tuple import locale from autosubmitconfigparser.config.configcommon import AutosubmitConfig as Autosubmit4Config @@ -69,8 +69,7 @@ SAFE_TIME_LIMIT = 300 SAFE_TIME_LIMIT_STATUS = 180 -def get_experiment_stats(expid, filter_period, filter_type): - # type: (str, int, str) -> Dict[str, Any] +def get_experiment_stats(expid: str, filter_period: int, filter_type: str) -> Dict[str, Any]: """ Lite version of the stats generator from Autosubmit autosubmit.py """ @@ -151,8 +150,14 @@ def get_experiment_data(expid): 'db_historic_version': "NA"} try: autosubmit_config_facade = ConfigurationFacadeDirector(AutosubmitConfigurationFacadeBuilder(expid)).build_autosubmit_configuration_facade() - _, experiment_status = DbRequests.get_specific_experiment_status(expid) - result["running"] = (experiment_status == "RUNNING") + try: + _, experiment_status = DbRequests.get_specific_experiment_status(expid) + result["running"] = (experiment_status == "RUNNING") + except Exception as exc: + logger.warning((traceback.format_exc())) + logger.warning((f"Warning: Error in get_experiment_data: {exc}. Trying to get the status exhaustively.")) + _, _, is_running, _, _ = _is_exp_running(expid) + result["running"] = is_running result["path"] = autosubmit_config_facade.experiment_path result["owner_id"] = autosubmit_config_facade.get_owner_id() result["owner"] = autosubmit_config_facade.get_owner_name() @@ -181,7 +186,7 @@ def get_experiment_data(expid): except Exception as exp: result["error"] = True result["error_message"] = str(exp) - print((traceback.format_exc())) + logger.error((traceback.format_exc())) return result @@ -199,13 +204,12 @@ def get_current_status_log_plus(expid): "log_path": log_path} -def _is_exp_running(expid, time_condition=300): +def _is_exp_running(expid: str, time_condition=300) -> Tuple[bool, str, bool, int, str]: """ Tests if experiment is running :param expid: Experiment name :param time_condition: Time constraint, 120 by default. Represents max seconds before an experiment is considered as NOT RUNNING :return: (error (true if error is found, false otherwise), error_message, is_running (true if running, false otherwise), timediff, path_to_log) - :rtype: tuple (bool, string, bool, int) """ is_running = False error = False @@ -225,14 +229,13 @@ def _is_exp_running(expid, time_condition=300): expid, APIBasicConfig, ConfigParserFactory()) as_conf.reload() current_version = as_conf.get_version() - except Exception as exp: - # print(exp) - pass + except Exception as exc: + logger.warning("Error in getting current_version: " + str(exc)) look_old_folder = True if current_version is not None and (str(current_version).startswith( "3.11") or str(current_version).startswith("3.9") or str(current_version).startswith("3.12")) else False - pathlog_first = pathlog_aslog if look_old_folder == False else pathlog_tmp - pathlog_second = pathlog_aslog if look_old_folder == True else pathlog_tmp + pathlog_first = pathlog_aslog if look_old_folder is False else pathlog_tmp + pathlog_second = pathlog_aslog if look_old_folder is True else pathlog_tmp # print("Experiment {0} version {1} \nLook {2} \nLook {3}".format( # expid, current_version, pathlog_first, pathlog_second)) # print(pathlog) @@ -313,8 +316,8 @@ def get_experiment_summary(expid, log): job_package_reader = JobPackageReader(expid) try: job_package_reader.read() - except: - logger.warning("Failed to read job_packages") + except Exception as exc: + logger.warning(f"Failed to read job_packages: {exc}") # Basic data job_running_to_seconds = dict() job_running_to_runtext = dict() @@ -359,7 +362,6 @@ def get_experiment_summary(expid, log): queue_seconds = job_info.queue_time if job_info else 0 running_seconds = job_info.run_time if job_info else 0 status = job_info.status if job_info else "UNKNOWN" - energy = job_info.energy if job_info else 0 # Identifying SIM name_components = job_name.split('_') if "SIM" in name_components: @@ -536,7 +538,6 @@ def get_job_log(expid, logfile, nlines=150): error = False error_message = "" logcontent = [] - reading = "" APIBasicConfig.read() exp_paths = ExperimentPaths(expid) logfilepath = os.path.join(exp_paths.tmp_log_dir, logfile) @@ -752,7 +753,6 @@ def get_experiment_tree_structured(expid, log): """ try: - notransitive = False APIBasicConfig.read() # TODO: Encapsulate this following 2 lines or move to the parent function in app.py @@ -812,18 +812,12 @@ def get_experiment_counters(expid): # TODO: Update to current representation standards and classes def get_quick_view(expid): """ Lighter View """ - pkl_file_name = "" error = False error_message = "" #quick_view = list() view_data = [] quick_tree_view = deque() - source = JobList.get_sourcetag() - target = JobList.get_targettag() - sync = JobList.get_synctag() - check_mark = JobList.get_checkmark() jobs_in_pkl = {} - fakeAllJobs = [] total_count = completed_count = failed_count = running_count = queuing_count = 0 try: APIBasicConfig.read() @@ -840,8 +834,8 @@ def get_quick_view(expid): job_package_reader.read() job_to_package = job_package_reader.job_to_package package_to_package_id = job_package_reader.package_to_package_id - except: - logger.warning("Failed to read job_packages") + except Exception as exc: + logger.warning(f"Failed to read job_packages: {exc}") logger.debug(("Retrieving packages {0} seconds.".format( str(time.time() - now_)))) @@ -872,9 +866,9 @@ def get_quick_view(expid): status_text = str(common_utils.Status.VALUE_TO_KEY[status_code]) jobs_in_pkl[job_name] = ( status_code, status_color, status_text, out, err, priority, id_number) - except Exception as exp: + except Exception as exc: raise Exception( - "Autosubmit API couldn't open pkl file. If you are sure that your experiment is running correctly, try again.") + f"Autosubmit API couldn't open pkl file. If you are sure that your experiment is running correctly, try again: {exc}") total_count = len(list(jobs_in_pkl.keys())) @@ -884,9 +878,9 @@ def get_quick_view(expid): job_name] wrapper_tag = "" wrapper_id = 0 - wrapper_name = "" + # wrapper_name = "" if job_name in list(job_to_package.keys()): - wrapper_name = job_to_package[job_name] + # wrapper_name = job_to_package[job_name] wrapper_id = package_to_package_id[job_to_package[job_name]] wrapper_tag = " Wrapped " + \ wrapper_id + "" @@ -909,8 +903,8 @@ def get_quick_view(expid): # return {} # quick_tree_view = list(quick_tree_view) - except Exception as exp: - error_message = "Exception: {0}".format(str(exp)) + except Exception as exc: + error_message = "Exception: {0}".format(str(exc)) error = True logger.error(error_message) logger.error(traceback.format_exc()) @@ -989,7 +983,7 @@ def get_current_configuration_by_expid(expid: str, user_id: Optional[str]): experimentRun = historicalDatabase.get_max_id_experiment_run() currentMetadata = json.loads( experimentRun.metadata) if experimentRun and experimentRun.metadata else None - currentRunId = experimentRun.run_id if experimentRun else None + # currentRunId = experimentRun.run_id if experimentRun else None # Main keys = conf, exp, jobs, platforms, proj # Can we ignore proj by now? Including it. # TODO: Define which keys should be included in the answer @@ -1199,7 +1193,7 @@ def test_esarchive_status(): clatency = result[4] DbRequests.insert_archive_status( status, alatency, abandwith, clatency, cbandwidth, rtime) - except Exception as exp: + except Exception: print((traceback.format_exc())) # error_message = str(exp) @@ -1225,9 +1219,9 @@ def get_last_test_archive_status(): rtime) > 1 else None else: str_status = "OFFLINE" - except Exception as exp: + except Exception as exc: error = True - error_message = "" + error_message = exc return {"status": str_status, "error": error, @@ -1247,14 +1241,14 @@ def enforceLocal(log): try: try: locale.setlocale(locale.LC_ALL, 'en_GB.UTF-8') - except Exception as e: + except Exception: try: locale.setlocale(locale.LC_ALL, 'C.utf8') - except Exception as e: + except Exception: try: locale.setlocale(locale.LC_ALL, 'en_GB') - except Exception as e: + except Exception: locale.setlocale(locale.LC_ALL, 'es_ES') - except Exception as e: + except Exception: log.info("Locale C.utf8 is not found, using '{0}' as fallback".format("C")) locale.setlocale(locale.LC_ALL, 'C') diff --git a/docs/source/_static/openapi.json b/docs/source/_static/openapi.json index d5b24179325fc518a550325b286d3860813e05a3..9b19e49345f9b9d5cbecab77287f8c897e735f60 100644 --- a/docs/source/_static/openapi.json +++ b/docs/source/_static/openapi.json @@ -9,177 +9,772 @@ } }, "paths": { + "/v3/login": { + "post": { + "tags": ["v3"], + "summary": "Login", + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/tokentest": { + "get": { + "tags": ["v3"], + "summary": "Token test", + "responses": { + "200": { + "description": "Success" + } + } + }, + "post": { + "tags": ["v3"], + "summary": "Token test", + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/updatedesc": { + "get": { + "tags": ["v3"], + "summary": "Update description", + "responses": { + "200": { + "description": "Success" + } + } + }, + "post": { + "tags": ["v3"], + "summary": "Update description", + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/cconfig/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get current configuration", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/expinfo/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment info", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/expcount/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment counters", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/searchowner/{owner}/{exptype}/{onlyactive}": { + "get": { + "tags": ["v3"], + "summary": "Search owner", + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "exptype", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "onlyactive", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/searchowner/{owner}": { + "get": { + "tags": ["v3"], + "summary": "Search owner", + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/search/{expid}/{exptype}/{onlyactive}": { + "get": { + "tags": ["v3"], + "summary": "Search experiment", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "exptype", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "onlyactive", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/search/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Search experiment", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, "/v3/running": { "get": { - "tags": [ - "v3" + "tags": ["v3"], + "summary": "Running experiments", + "operationId": "get-v3-running", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "experiment": { + "type": "array", + "items": { + "type": "object", + "properties": { + "completed": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "failed": { + "type": "integer" + }, + "hpc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "modified": { + "type": "string" + }, + "name": { + "type": "string" + }, + "queuing": { + "type": "integer" + }, + "running": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "submitted": { + "type": "integer" + }, + "suspended": { + "type": "integer" + }, + "total": { + "type": "integer" + }, + "user": { + "type": "string" + }, + "version": { + "type": "string" + }, + "wrapper": { + "type": "string", + "nullable": true + } + } + } + } + } + }, + "examples": { + "Example 1": { + "value": { + "experiment": [ + { + "completed": 25, + "description": "Testing AS 4.0", + "failed": 8, + "hpc": "MARENOSTRUM4", + "id": 8192, + "modified": "2022-10-03 10:05:27", + "name": "a4yd", + "queuing": 0, + "running": 0, + "status": "RUNNING", + "submitted": 0, + "suspended": 0, + "total": 385, + "user": "root", + "version": "4.0.0b0", + "wrapper": null + }, + { + "completed": 88, + "description": "TEST_AS_4.0", + "failed": 0, + "hpc": "MARENOSTRUM4", + "id": 8202, + "modified": "2022-11-30 11:50:29", + "name": "t0an", + "queuing": 0, + "running": 0, + "status": "RUNNING", + "submitted": 0, + "suspended": 0, + "total": 91, + "user": "root", + "version": "4.0.0b0", + "wrapper": null + } + ] + } + } + } + } + } + } + } + } + }, + "/v3/runs/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get runs", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/ifrun/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get if running", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/logrun/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get status and log path experiment", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/summary/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment summary", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/shutdown/{route}": { + "get": { + "tags": ["v3"], + "summary": "Shutdown route", + "parameters": [ + { + "name": "route", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/performance/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment performance metrics", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/graph/{expid}/{layout}/{grouped}": { + "get": { + "tags": ["v3"], + "summary": "Get graph format", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "layout", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "grouped", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/tree/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment tree", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/quick/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get quick view data", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/exprun/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment run log", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/joblog/{logfile}": { + "get": { + "tags": ["v3"], + "summary": "Get job log from path", + "parameters": [ + { + "name": "logfile", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/pklinfo/{expid}/{timeStamp}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment pklinfo", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "timeStamp", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/pkltreeinfo/{expid}/{timeStamp}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment tree pklinfo", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "timeStamp", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/stats/{expid}/{filter_period}/{filter_type}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment statistics", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "filter_period", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "filter_type", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/history/{expid}/{jobname}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment job history", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "jobname", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } ], - "summary": "Running experiments", - "operationId": "get-v3-running", "responses": { "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "experiment": { - "type": "array", - "items": { - "type": "object", - "properties": { - "completed": { - "type": "integer" - }, - "description": { - "type": "string" - }, - "failed": { - "type": "integer" - }, - "hpc": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "modified": { - "type": "string" - }, - "name": { - "type": "string" - }, - "queuing": { - "type": "integer" - }, - "running": { - "type": "integer" - }, - "status": { - "type": "string" - }, - "submitted": { - "type": "integer" - }, - "suspended": { - "type": "integer" - }, - "total": { - "type": "integer" - }, - "user": { - "type": "string" - }, - "version": { - "type": "string" - }, - "wrapper": { - "type": "string", - "nullable": true - } - } - } - } - }, - "x-examples": { - "Example 1": { - "experiment": [ - { - "completed": 25, - "description": "Testing AS 4.0", - "failed": 8, - "hpc": "MARENOSTRUM4", - "id": 8192, - "modified": "2022-10-03 10:05:27", - "name": "a4yd", - "queuing": 0, - "running": 0, - "status": "RUNNING", - "submitted": 0, - "suspended": 0, - "total": 385, - "user": "root", - "version": "4.0.0b0", - "wrapper": null - }, - { - "completed": 88, - "description": "TEST_AS_4.0", - "failed": 0, - "hpc": "MARENOSTRUM4", - "id": 8202, - "modified": "2022-11-30 11:50:29", - "name": "t0an", - "queuing": 0, - "running": 0, - "status": "RUNNING", - "submitted": 0, - "suspended": 0, - "total": 91, - "user": "root", - "version": "4.0.0b0", - "wrapper": null - } - ] - } - } - }, - "examples": { - "Example 1": { - "value": { - "experiment": [ - { - "completed": 25, - "description": "Testing AS 4.0", - "failed": 8, - "hpc": "MARENOSTRUM4", - "id": 8192, - "modified": "2022-10-03 10:05:27", - "name": "a4yd", - "queuing": 0, - "running": 0, - "status": "RUNNING", - "submitted": 0, - "suspended": 0, - "total": 385, - "user": "root", - "version": "4.0.0b0", - "wrapper": null - }, - { - "completed": 88, - "description": "TEST_AS_4.0", - "failed": 0, - "hpc": "MARENOSTRUM4", - "id": 8202, - "modified": "2022-11-30 11:50:29", - "name": "t0an", - "queuing": 0, - "running": 0, - "status": "RUNNING", - "submitted": 0, - "suspended": 0, - "total": 91, - "user": "root", - "version": "4.0.0b0", - "wrapper": null - } - ] - } - } - } - } + "description": "Success" + } + } + } + }, + "/v3/rundetail/{expid}/{runid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment run job detail", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" } + }, + { + "name": "runid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/filestatus/": { + "get": { + "tags": ["v3"], + "summary": "[LEGACY] Get file status", + "responses": { + "200": { + "description": "Success" } } } }, "/v4/experiments": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "Search experiments", "description": "", "operationId": "get-v4-experiments", @@ -210,11 +805,7 @@ "in": "query", "schema": { "type": "string", - "enum": [ - "test", - "operational", - "experiment" - ] + "enum": ["test", "operational", "experiment"] } }, { @@ -229,11 +820,7 @@ "in": "query", "schema": { "type": "string", - "enum": [ - "expid", - "created", - "description" - ] + "enum": ["expid", "created", "description"] } }, { @@ -346,55 +933,6 @@ } } } - }, - "x-examples": { - "Example 1": { - "experiments": [ - { - "completed": 0, - "description": "DE Model App", - "failed": 0, - "hpc": null, - "id": 9, - "modified": null, - "name": "a005", - "queuing": 0, - "running": 0, - "status": "NOT RUNNING", - "submitted": 0, - "suspended": 0, - "total": 0, - "user": null, - "version": "Unknown", - "wrapper": null - }, - { - "completed": 115, - "description": "DE downstream", - "failed": 0, - "hpc": "LOCAL", - "id": 11, - "modified": "2023-10-26 11:44:07", - "name": "a006", - "queuing": 0, - "running": 0, - "status": "NOT RUNNING", - "submitted": 0, - "suspended": 0, - "total": 115, - "user": "ltenorio", - "version": "4.0.95", - "wrapper": null - } - ], - "pagination": { - "page": 1, - "page_items": 2, - "page_size": 2, - "total_items": 9, - "total_pages": 5 - } - } } }, "examples": { @@ -456,9 +994,7 @@ }, "/v4/experiments/{expid}": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "Get experiment info", "operationId": "get-v4-experiments-expid", "parameters": [ @@ -471,14 +1007,16 @@ } } ], - "responses": {} + "responses": { + "200": { + "description": "OK" + } + } } }, "/v4/experiments/{expid}/jobs": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "List experiment jobs", "operationId": "get-v4-experiments-expid-jobs", "parameters": [ @@ -488,10 +1026,7 @@ "description": "Data view selector", "schema": { "type": "string", - "enum": [ - "base", - "quick" - ] + "enum": ["base", "quick"] } }, { @@ -548,9 +1083,7 @@ }, "/v4/experiments/{expid}/wrappers": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "List experiment wrappers", "operationId": "get-v4-experiments-expid-wrappers", "parameters": [ @@ -588,34 +1121,6 @@ } } } - }, - "x-examples": { - "Example 1": { - "wrappers": [ - { - "job_names": [ - "a6zi_18500101_fc0_1_SIM", - "a6zi_18500101_fc0_2_SIM" - ], - "wrapper_name": "a6zi_ASThread_17108563159474_528_10" - }, - { - "job_names": [ - "a6zi_18500101_fc0_3_SIM", - "a6zi_18500101_fc0_4_SIM", - "a6zi_18500101_fc0_5_SIM", - "a6zi_18500101_fc0_6_SIM", - "a6zi_18500101_fc0_7_SIM", - "a6zi_18500101_fc0_8_SIM", - "a6zi_18500101_fc0_9_SIM", - "a6zi_18500101_fc0_10_SIM", - "a6zi_18500101_fc0_11_SIM", - "a6zi_18500101_fc0_12_SIM" - ], - "wrapper_name": "a6zi_ASThread_17108816522924_528_10" - } - ] - } } } } @@ -626,9 +1131,7 @@ }, "/v4/auth/verify-token": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "Verify JWT Token", "operationId": "get-v4-auth-verify-token", "parameters": [ @@ -701,9 +1204,7 @@ }, "/v4/auth/cas/v2/login": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "CAS v2 Login", "operationId": "get-v4-auth-cas-v2-login", "parameters": [ @@ -803,9 +1304,7 @@ }, "/v4/auth/oauth2/github/login": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "GitHub Oauth2 App Login", "operationId": "get-v4-auth-oauth2-github-login", "parameters": [ @@ -867,10 +1366,12 @@ "type": "string" }, "token": { - "type": "string" + "type": "string", + "nullable": true }, "user": { - "type": "string" + "type": "string", + "nullable": true } } }, @@ -950,23 +1451,8 @@ "err_path_remote": { "type": "string" } - }, - "x-examples": { - "Example 1": { - "name": "a008_20200120_fc0_2_SIM", - "status": "COMPLETED", - "priority": 4, - "section": "SIM", - "date": "2020-01-20T00:00:00", - "member": "fc0", - "chunk": 2, - "out_path_local": "a008_20200120_fc0_2_SIM.20231027153508.out", - "err_path_local": "a008_20200120_fc0_2_SIM.20231027153508.err", - "out_path_remote": "a008_20200120_fc0_2_SIM.20231027153508.out", - "err_path_remote": "a008_20200120_fc0_2_SIM.20231027153508.err" - } } } } } -} \ No newline at end of file +} diff --git a/docs/source/conf.py b/docs/source/conf.py index 1af25c71cb3198d165a3593b3f06d1085a168e82..b591128366f419e93478fe067d4b57f699488efa 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -24,6 +24,10 @@ redoc = [ 'spec': '_static/openapi.json', # 'spec': 'https://petstore3.swagger.io/api/v3/openapi.json', # 'spec': 'https://petstore.swagger.io/v2/swagger.json' + 'opts': { + 'suppress-warnings': True, + 'hide-hostname': True + } } ] diff --git a/openapi.json b/openapi.json index d5b24179325fc518a550325b286d3860813e05a3..9b19e49345f9b9d5cbecab77287f8c897e735f60 100644 --- a/openapi.json +++ b/openapi.json @@ -9,177 +9,772 @@ } }, "paths": { + "/v3/login": { + "post": { + "tags": ["v3"], + "summary": "Login", + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/tokentest": { + "get": { + "tags": ["v3"], + "summary": "Token test", + "responses": { + "200": { + "description": "Success" + } + } + }, + "post": { + "tags": ["v3"], + "summary": "Token test", + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/updatedesc": { + "get": { + "tags": ["v3"], + "summary": "Update description", + "responses": { + "200": { + "description": "Success" + } + } + }, + "post": { + "tags": ["v3"], + "summary": "Update description", + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/cconfig/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get current configuration", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/expinfo/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment info", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/expcount/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment counters", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/searchowner/{owner}/{exptype}/{onlyactive}": { + "get": { + "tags": ["v3"], + "summary": "Search owner", + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "exptype", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "onlyactive", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/searchowner/{owner}": { + "get": { + "tags": ["v3"], + "summary": "Search owner", + "parameters": [ + { + "name": "owner", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/search/{expid}/{exptype}/{onlyactive}": { + "get": { + "tags": ["v3"], + "summary": "Search experiment", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "exptype", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "onlyactive", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/search/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Search experiment", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, "/v3/running": { "get": { - "tags": [ - "v3" + "tags": ["v3"], + "summary": "Running experiments", + "operationId": "get-v3-running", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "experiment": { + "type": "array", + "items": { + "type": "object", + "properties": { + "completed": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "failed": { + "type": "integer" + }, + "hpc": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "modified": { + "type": "string" + }, + "name": { + "type": "string" + }, + "queuing": { + "type": "integer" + }, + "running": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "submitted": { + "type": "integer" + }, + "suspended": { + "type": "integer" + }, + "total": { + "type": "integer" + }, + "user": { + "type": "string" + }, + "version": { + "type": "string" + }, + "wrapper": { + "type": "string", + "nullable": true + } + } + } + } + } + }, + "examples": { + "Example 1": { + "value": { + "experiment": [ + { + "completed": 25, + "description": "Testing AS 4.0", + "failed": 8, + "hpc": "MARENOSTRUM4", + "id": 8192, + "modified": "2022-10-03 10:05:27", + "name": "a4yd", + "queuing": 0, + "running": 0, + "status": "RUNNING", + "submitted": 0, + "suspended": 0, + "total": 385, + "user": "root", + "version": "4.0.0b0", + "wrapper": null + }, + { + "completed": 88, + "description": "TEST_AS_4.0", + "failed": 0, + "hpc": "MARENOSTRUM4", + "id": 8202, + "modified": "2022-11-30 11:50:29", + "name": "t0an", + "queuing": 0, + "running": 0, + "status": "RUNNING", + "submitted": 0, + "suspended": 0, + "total": 91, + "user": "root", + "version": "4.0.0b0", + "wrapper": null + } + ] + } + } + } + } + } + } + } + } + }, + "/v3/runs/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get runs", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/ifrun/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get if running", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/logrun/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get status and log path experiment", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/summary/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment summary", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/shutdown/{route}": { + "get": { + "tags": ["v3"], + "summary": "Shutdown route", + "parameters": [ + { + "name": "route", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/performance/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment performance metrics", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/graph/{expid}/{layout}/{grouped}": { + "get": { + "tags": ["v3"], + "summary": "Get graph format", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "layout", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "grouped", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/tree/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment tree", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/quick/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get quick view data", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/exprun/{expid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment run log", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/joblog/{logfile}": { + "get": { + "tags": ["v3"], + "summary": "Get job log from path", + "parameters": [ + { + "name": "logfile", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/pklinfo/{expid}/{timeStamp}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment pklinfo", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "timeStamp", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/pkltreeinfo/{expid}/{timeStamp}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment tree pklinfo", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "timeStamp", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/stats/{expid}/{filter_period}/{filter_type}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment statistics", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "filter_period", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "filter_type", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/history/{expid}/{jobname}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment job history", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "jobname", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } ], - "summary": "Running experiments", - "operationId": "get-v3-running", "responses": { "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "experiment": { - "type": "array", - "items": { - "type": "object", - "properties": { - "completed": { - "type": "integer" - }, - "description": { - "type": "string" - }, - "failed": { - "type": "integer" - }, - "hpc": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "modified": { - "type": "string" - }, - "name": { - "type": "string" - }, - "queuing": { - "type": "integer" - }, - "running": { - "type": "integer" - }, - "status": { - "type": "string" - }, - "submitted": { - "type": "integer" - }, - "suspended": { - "type": "integer" - }, - "total": { - "type": "integer" - }, - "user": { - "type": "string" - }, - "version": { - "type": "string" - }, - "wrapper": { - "type": "string", - "nullable": true - } - } - } - } - }, - "x-examples": { - "Example 1": { - "experiment": [ - { - "completed": 25, - "description": "Testing AS 4.0", - "failed": 8, - "hpc": "MARENOSTRUM4", - "id": 8192, - "modified": "2022-10-03 10:05:27", - "name": "a4yd", - "queuing": 0, - "running": 0, - "status": "RUNNING", - "submitted": 0, - "suspended": 0, - "total": 385, - "user": "root", - "version": "4.0.0b0", - "wrapper": null - }, - { - "completed": 88, - "description": "TEST_AS_4.0", - "failed": 0, - "hpc": "MARENOSTRUM4", - "id": 8202, - "modified": "2022-11-30 11:50:29", - "name": "t0an", - "queuing": 0, - "running": 0, - "status": "RUNNING", - "submitted": 0, - "suspended": 0, - "total": 91, - "user": "root", - "version": "4.0.0b0", - "wrapper": null - } - ] - } - } - }, - "examples": { - "Example 1": { - "value": { - "experiment": [ - { - "completed": 25, - "description": "Testing AS 4.0", - "failed": 8, - "hpc": "MARENOSTRUM4", - "id": 8192, - "modified": "2022-10-03 10:05:27", - "name": "a4yd", - "queuing": 0, - "running": 0, - "status": "RUNNING", - "submitted": 0, - "suspended": 0, - "total": 385, - "user": "root", - "version": "4.0.0b0", - "wrapper": null - }, - { - "completed": 88, - "description": "TEST_AS_4.0", - "failed": 0, - "hpc": "MARENOSTRUM4", - "id": 8202, - "modified": "2022-11-30 11:50:29", - "name": "t0an", - "queuing": 0, - "running": 0, - "status": "RUNNING", - "submitted": 0, - "suspended": 0, - "total": 91, - "user": "root", - "version": "4.0.0b0", - "wrapper": null - } - ] - } - } - } - } + "description": "Success" + } + } + } + }, + "/v3/rundetail/{expid}/{runid}": { + "get": { + "tags": ["v3"], + "summary": "Get experiment run job detail", + "parameters": [ + { + "name": "expid", + "in": "path", + "required": true, + "schema": { + "type": "string" } + }, + { + "name": "runid", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/v3/filestatus/": { + "get": { + "tags": ["v3"], + "summary": "[LEGACY] Get file status", + "responses": { + "200": { + "description": "Success" } } } }, "/v4/experiments": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "Search experiments", "description": "", "operationId": "get-v4-experiments", @@ -210,11 +805,7 @@ "in": "query", "schema": { "type": "string", - "enum": [ - "test", - "operational", - "experiment" - ] + "enum": ["test", "operational", "experiment"] } }, { @@ -229,11 +820,7 @@ "in": "query", "schema": { "type": "string", - "enum": [ - "expid", - "created", - "description" - ] + "enum": ["expid", "created", "description"] } }, { @@ -346,55 +933,6 @@ } } } - }, - "x-examples": { - "Example 1": { - "experiments": [ - { - "completed": 0, - "description": "DE Model App", - "failed": 0, - "hpc": null, - "id": 9, - "modified": null, - "name": "a005", - "queuing": 0, - "running": 0, - "status": "NOT RUNNING", - "submitted": 0, - "suspended": 0, - "total": 0, - "user": null, - "version": "Unknown", - "wrapper": null - }, - { - "completed": 115, - "description": "DE downstream", - "failed": 0, - "hpc": "LOCAL", - "id": 11, - "modified": "2023-10-26 11:44:07", - "name": "a006", - "queuing": 0, - "running": 0, - "status": "NOT RUNNING", - "submitted": 0, - "suspended": 0, - "total": 115, - "user": "ltenorio", - "version": "4.0.95", - "wrapper": null - } - ], - "pagination": { - "page": 1, - "page_items": 2, - "page_size": 2, - "total_items": 9, - "total_pages": 5 - } - } } }, "examples": { @@ -456,9 +994,7 @@ }, "/v4/experiments/{expid}": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "Get experiment info", "operationId": "get-v4-experiments-expid", "parameters": [ @@ -471,14 +1007,16 @@ } } ], - "responses": {} + "responses": { + "200": { + "description": "OK" + } + } } }, "/v4/experiments/{expid}/jobs": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "List experiment jobs", "operationId": "get-v4-experiments-expid-jobs", "parameters": [ @@ -488,10 +1026,7 @@ "description": "Data view selector", "schema": { "type": "string", - "enum": [ - "base", - "quick" - ] + "enum": ["base", "quick"] } }, { @@ -548,9 +1083,7 @@ }, "/v4/experiments/{expid}/wrappers": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "List experiment wrappers", "operationId": "get-v4-experiments-expid-wrappers", "parameters": [ @@ -588,34 +1121,6 @@ } } } - }, - "x-examples": { - "Example 1": { - "wrappers": [ - { - "job_names": [ - "a6zi_18500101_fc0_1_SIM", - "a6zi_18500101_fc0_2_SIM" - ], - "wrapper_name": "a6zi_ASThread_17108563159474_528_10" - }, - { - "job_names": [ - "a6zi_18500101_fc0_3_SIM", - "a6zi_18500101_fc0_4_SIM", - "a6zi_18500101_fc0_5_SIM", - "a6zi_18500101_fc0_6_SIM", - "a6zi_18500101_fc0_7_SIM", - "a6zi_18500101_fc0_8_SIM", - "a6zi_18500101_fc0_9_SIM", - "a6zi_18500101_fc0_10_SIM", - "a6zi_18500101_fc0_11_SIM", - "a6zi_18500101_fc0_12_SIM" - ], - "wrapper_name": "a6zi_ASThread_17108816522924_528_10" - } - ] - } } } } @@ -626,9 +1131,7 @@ }, "/v4/auth/verify-token": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "Verify JWT Token", "operationId": "get-v4-auth-verify-token", "parameters": [ @@ -701,9 +1204,7 @@ }, "/v4/auth/cas/v2/login": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "CAS v2 Login", "operationId": "get-v4-auth-cas-v2-login", "parameters": [ @@ -803,9 +1304,7 @@ }, "/v4/auth/oauth2/github/login": { "get": { - "tags": [ - "v4" - ], + "tags": ["v4"], "summary": "GitHub Oauth2 App Login", "operationId": "get-v4-auth-oauth2-github-login", "parameters": [ @@ -867,10 +1366,12 @@ "type": "string" }, "token": { - "type": "string" + "type": "string", + "nullable": true }, "user": { - "type": "string" + "type": "string", + "nullable": true } } }, @@ -950,23 +1451,8 @@ "err_path_remote": { "type": "string" } - }, - "x-examples": { - "Example 1": { - "name": "a008_20200120_fc0_2_SIM", - "status": "COMPLETED", - "priority": 4, - "section": "SIM", - "date": "2020-01-20T00:00:00", - "member": "fc0", - "chunk": 2, - "out_path_local": "a008_20200120_fc0_2_SIM.20231027153508.out", - "err_path_local": "a008_20200120_fc0_2_SIM.20231027153508.err", - "out_path_remote": "a008_20200120_fc0_2_SIM.20231027153508.out", - "err_path_remote": "a008_20200120_fc0_2_SIM.20231027153508.err" - } } } } } -} \ No newline at end of file +} diff --git a/setup.py b/setup.py index 8eb87b2f76389b0717447cd8068c1bcba08d5453..06ebda7f003432a77fe97c0595d3875631211173 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,6 @@ install_requires = [ "portalocker~=2.6.0", "networkx~=2.6.3", "scipy~=1.7.3", - "paramiko~=2.12.0", "python-dotenv", "autosubmitconfigparser~=1.0.48", "autosubmit>=3.13", @@ -38,8 +37,7 @@ install_requires = [ "gunicorn", "pydantic~=2.5.2", "SQLAlchemy~=2.0.23", - "python-cas>=1.6.0", - "Authlib>=1.3.0" + "python-cas>=1.6.0" ] # Test dependencies diff --git a/tests/bgtasks/test_status_updater.py b/tests/bgtasks/test_status_updater.py index 6d2302956f97ffeb4eb5df736b4e3dfa6fbdece4..c6975a9b5f8fb5e4a72886e4e025b9c40a7db729 100644 --- a/tests/bgtasks/test_status_updater.py +++ b/tests/bgtasks/test_status_updater.py @@ -6,22 +6,25 @@ from autosubmit_api.database.common import ( ) from autosubmit_api.history.database_managers.database_models import RunningStatus -class TestStatusUpdater: +class TestStatusUpdater: def test_same_tables(self, fixture_mock_basic_config): prepare_db() - + + with create_as_times_db_engine().connect() as conn: + exps_status = conn.execute(tables.experiment_status_table.delete()) + StatusUpdater.run() - + with create_autosubmit_db_engine().connect() as conn: experiments = conn.execute(tables.experiment_table.select()).all() - + with create_as_times_db_engine().connect() as conn: exps_status = conn.execute(tables.experiment_status_table.select()).all() assert len(experiments) == len(exps_status) assert set([x.id for x in experiments]) == set([x.exp_id for x in exps_status]) assert set([x.name for x in experiments]) == set([x.name for x in exps_status]) - + for e_st in exps_status: assert e_st.status in [RunningStatus.RUNNING, RunningStatus.NOT_RUNNING] diff --git a/tests/experiments/autosubmit.db b/tests/experiments/autosubmit.db index fdca9705b5a01cac55d77fb350ce34b868e060df..472787336d33e91b529d921869dcc82dea543426 100644 Binary files a/tests/experiments/autosubmit.db and b/tests/experiments/autosubmit.db differ diff --git a/tests/experiments/metadata/graph/graph_data_a003.db b/tests/experiments/metadata/graph/graph_data_a003.db index 41b2c4f84c4a700e3a35394a2aea257543e762d4..1862073cccbab88a43d010644c5c6316b4202aa1 100755 Binary files a/tests/experiments/metadata/graph/graph_data_a003.db and b/tests/experiments/metadata/graph/graph_data_a003.db differ diff --git a/tests/test_database.py b/tests/test_database.py new file mode 100644 index 0000000000000000000000000000000000000000..518523b3705220b6a9d8bcb41fe485f215c7b72b --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,29 @@ +import os + +from sqlalchemy import select + +from autosubmit_api.database import common, tables + + +def count_pid_lsof(pid): + openfiles = os.popen(f"lsof -p {pid} | grep db").read() + print(openfiles) + return len([x for x in openfiles.strip("\n ").split("\n") if len(x.strip()) > 0]) + + +class TestDatabase: + + def test_open_files(self, fixture_mock_basic_config): + current_pid = os.getpid() + + counter = count_pid_lsof(current_pid) + + engine = common.create_autosubmit_db_engine() + + assert counter == count_pid_lsof(current_pid) + + with engine.connect() as conn: + conn.execute(select(tables.ExperimentTable)) + assert counter + 1 == count_pid_lsof(current_pid) + + assert counter == count_pid_lsof(current_pid)