diff --git a/dapi/jobs/jobs.py b/dapi/jobs/jobs.py index 22e9c4c..3b51c12 100644 --- a/dapi/jobs/jobs.py +++ b/dapi/jobs/jobs.py @@ -62,14 +62,22 @@ def generate_job_info( or app_info.jobAttributes.execSystemLogicalQueue, "nodeCount": node_count or 1, # Default to 1 if not specified "coresPerNode": cores_per_node or 1, # Default to 1 if not specified - "parameterSet": { - "appArgs": [{"name": "Input Script", "arg": input_file}], - "schedulerOptions": [], - }, } + # Handle input file based on app name + if "opensees" in app_name.lower(): + job_info["parameterSet"] = { + "envVariables": [{"key": "tclScript", "value": input_file}] + } + else: + job_info["parameterSet"] = { + "appArgs": [{"name": "Input Script", "arg": input_file}] + } + # Add TACC allocation if provided if allocation: + if "schedulerOptions" not in job_info["parameterSet"]: + job_info["parameterSet"]["schedulerOptions"] = [] job_info["parameterSet"]["schedulerOptions"].append( {"name": "TACC Allocation", "arg": f"-A {allocation}"} ) diff --git a/examples/mpm/template-mpm-v3.ipynb b/examples/mpm/template-mpm-v3.ipynb index 29fafd1..5a2f721 100644 --- a/examples/mpm/template-mpm-v3.ipynb +++ b/examples/mpm/template-mpm-v3.ipynb @@ -31,115 +31,12 @@ } ], "source": [ - "!pip install --user --upgrade setuptools" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "bc693a16-4a20-4289-9e32-bfb3da4df601", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: atomicwrites==1.4.0 in /home/kks32/.local/lib/python3.10/site-packages (1.4.0)\n" - ] - } - ], - "source": [ - "!pip install --user --only-binary=:all: atomicwrites==1.4.0" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "ddb991fa-5bee-4e8e-94bf-982601cfa753", - "metadata": {}, - "outputs": [], - "source": [ - "!pip install --user jsonschema>=4.18.0" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "99f68a43-7d8d-4349-a88f-2ddb3be81a28", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Collecting git+https://github.com/DesignSafe-CI/dapi.git@tapisv3\n", - " Cloning https://github.com/DesignSafe-CI/dapi.git (to revision tapisv3) to /tmp/pip-req-build-rlxjpkq5\n", - " Running command git clone --filter=blob:none --quiet https://github.com/DesignSafe-CI/dapi.git /tmp/pip-req-build-rlxjpkq5\n", - " Running command git checkout -b tapisv3 --track origin/tapisv3\n", - " Switched to a new branch 'tapisv3'\n", - " Branch 'tapisv3' set up to track remote branch 'tapisv3' from 'origin'.\n", - " Resolved https://github.com/DesignSafe-CI/dapi.git to commit 93eb0c04a3e37805c9ee695b8bbf3ab74ad8d4aa\n", - " Installing build dependencies ... \u001b[?25ldone\n", - "\u001b[?25h Getting requirements to build wheel ... \u001b[?25ldone\n", - "\u001b[?25h Preparing metadata (pyproject.toml) ... \u001b[?25ldone\n", - "\u001b[?25hRequirement already satisfied: exceptiongroup<2.0.0,>=1.2.0 in /home/kks32/.local/lib/python3.10/site-packages (from dapi==1.0.0) (1.2.2)\n", - "Requirement already satisfied: numpy<3.0.0,>=2.1.1 in /home/kks32/.local/lib/python3.10/site-packages (from dapi==1.0.0) (2.1.1)\n", - "Requirement already satisfied: pandas<3.0.0,>=2.2.3 in /home/kks32/.local/lib/python3.10/site-packages (from dapi==1.0.0) (2.2.3)\n", - "Requirement already satisfied: pymysql<2.0.0,>=1.1.0 in /home/kks32/.local/lib/python3.10/site-packages (from dapi==1.0.0) (1.1.1)\n", - "Requirement already satisfied: python-dotenv<2.0.0,>=1.0.1 in /home/kks32/.local/lib/python3.10/site-packages (from dapi==1.0.0) (1.0.1)\n", - "Requirement already satisfied: sqlalchemy<3.0.0,>=2.0.23 in /home/kks32/.local/lib/python3.10/site-packages (from dapi==1.0.0) (2.0.35)\n", - "Requirement already satisfied: tapipy<2.0.0,>=1.6.3 in /home/kks32/.local/lib/python3.10/site-packages (from dapi==1.0.0) (1.6.3)\n", - "Requirement already satisfied: tqdm<5.0.0,>=4.66.1 in /home/kks32/.local/lib/python3.10/site-packages (from dapi==1.0.0) (4.66.5)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in /opt/conda/lib/python3.10/site-packages (from pandas<3.0.0,>=2.2.3->dapi==1.0.0) (2.8.2)\n", - "Requirement already satisfied: pytz>=2020.1 in /opt/conda/lib/python3.10/site-packages (from pandas<3.0.0,>=2.2.3->dapi==1.0.0) (2022.4)\n", - "Requirement already satisfied: tzdata>=2022.7 in /opt/conda/lib/python3.10/site-packages (from pandas<3.0.0,>=2.2.3->dapi==1.0.0) (2024.1)\n", - "Requirement already satisfied: typing-extensions>=4.6.0 in /home/kks32/.local/lib/python3.10/site-packages (from sqlalchemy<3.0.0,>=2.0.23->dapi==1.0.0) (4.12.2)\n", - "Requirement already satisfied: greenlet!=0.4.17 in /opt/conda/lib/python3.10/site-packages (from sqlalchemy<3.0.0,>=2.0.23->dapi==1.0.0) (1.1.3)\n", - "Requirement already satisfied: PyJWT>=1.7.1 in /opt/conda/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (2.5.0)\n", - "Requirement already satisfied: atomicwrites<2.0.0,>=1.4.0 in /home/kks32/.local/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (1.4.0)\n", - "Requirement already satisfied: certifi>=2020.11.8 in /opt/conda/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (2022.9.24)\n", - "Requirement already satisfied: cloudpickle>=1.6.0 in /home/kks32/.local/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (3.0.0)\n", - "Requirement already satisfied: cryptography>=3.3.2 in /opt/conda/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (38.0.1)\n", - "Requirement already satisfied: jsonschema>=3.2.0 in /home/kks32/.local/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (4.17.3)\n", - "Requirement already satisfied: openapi_core==0.16.0 in /home/kks32/.local/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (0.16.0)\n", - "Requirement already satisfied: openapi_spec_validator<0.6.0,>=0.5.0 in /home/kks32/.local/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (0.5.4)\n", - "Requirement already satisfied: pyyaml>=5.4 in /opt/conda/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (6.0.2)\n", - "Requirement already satisfied: requests<3.0.0,>=2.20.0 in /opt/conda/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (2.32.3)\n", - "Requirement already satisfied: setuptools>=21.0.0 in /home/kks32/.local/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (75.1.0)\n", - "Requirement already satisfied: six<2.0,>=1.10 in /opt/conda/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (1.16.0)\n", - "Requirement already satisfied: urllib3<2.0.0,>=1.26.5 in /opt/conda/lib/python3.10/site-packages (from tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (1.26.11)\n", - "Requirement already satisfied: isodate in /home/kks32/.local/lib/python3.10/site-packages (from openapi_core==0.16.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (0.6.1)\n", - "Requirement already satisfied: jsonschema-spec<0.2.0,>=0.1.1 in /home/kks32/.local/lib/python3.10/site-packages (from openapi_core==0.16.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (0.1.6)\n", - "Requirement already satisfied: more-itertools in /home/kks32/.local/lib/python3.10/site-packages (from openapi_core==0.16.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (10.5.0)\n", - "Requirement already satisfied: openapi-schema-validator<0.4.0,>=0.3.0 in /home/kks32/.local/lib/python3.10/site-packages (from openapi_core==0.16.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (0.3.4)\n", - "Requirement already satisfied: parse in /home/kks32/.local/lib/python3.10/site-packages (from openapi_core==0.16.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (1.20.2)\n", - "Requirement already satisfied: pathable<0.5.0,>=0.4.0 in /home/kks32/.local/lib/python3.10/site-packages (from openapi_core==0.16.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (0.4.3)\n", - "Requirement already satisfied: werkzeug in /home/kks32/.local/lib/python3.10/site-packages (from openapi_core==0.16.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (3.0.4)\n", - "Requirement already satisfied: cffi>=1.12 in /opt/conda/lib/python3.10/site-packages (from cryptography>=3.3.2->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (1.15.1)\n", - "Requirement already satisfied: attrs>=17.4.0 in /opt/conda/lib/python3.10/site-packages (from jsonschema>=3.2.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (24.2.0)\n", - "Requirement already satisfied: pyrsistent!=0.17.0,!=0.17.1,!=0.17.2,>=0.14.0 in /opt/conda/lib/python3.10/site-packages (from jsonschema>=3.2.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (0.18.1)\n", - "Requirement already satisfied: lazy-object-proxy<2.0.0,>=1.7.1 in /home/kks32/.local/lib/python3.10/site-packages (from openapi_spec_validator<0.6.0,>=0.5.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (1.10.0)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.10/site-packages (from requests<3.0.0,>=2.20.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (2.1.1)\n", - "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.10/site-packages (from requests<3.0.0,>=2.20.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (3.4)\n", - "Requirement already satisfied: pycparser in /opt/conda/lib/python3.10/site-packages (from cffi>=1.12->cryptography>=3.3.2->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (2.21)\n", - "Requirement already satisfied: MarkupSafe>=2.1.1 in /opt/conda/lib/python3.10/site-packages (from werkzeug->openapi_core==0.16.0->tapipy<2.0.0,>=1.6.3->dapi==1.0.0) (2.1.1)\n" - ] - } - ], - "source": [ + "!pip install --user --upgrade setuptools\n", + "!pip install --user --only-binary=:all: atomicwrites==1.4.0\n", + "!pip install --user jsonschema<4.18.0\n", "!pip install git+https://github.com/DesignSafe-CI/dapi.git@tapisv3 --user" ] }, - { - "cell_type": "code", - "execution_count": 5, - "id": "b7fa3e9a-7bf3-441c-917f-fb57a94ee017", - "metadata": {}, - "outputs": [], - "source": [ - "#!pip install dapi --quiet" - ] - }, { "cell_type": "markdown", "id": "dd802d14-8cb5-49e7-b43c-1c21ac253961", diff --git a/tests/jobs/test_job_gen_jobinfo.py b/tests/jobs/test_job_gen_jobinfo.py index 9128d21..a802c32 100644 --- a/tests/jobs/test_job_gen_jobinfo.py +++ b/tests/jobs/test_job_gen_jobinfo.py @@ -10,7 +10,6 @@ def setUp(self): self.app_name = "test-app" self.input_uri = "tapis://test-system/input/data" self.input_file = "input.txt" - # Mock the getAppLatestVersion method self.app_info_mock = Mock() self.app_info_mock.id = self.app_name @@ -24,11 +23,9 @@ def setUp(self): @patch("dapi.jobs.jobs.datetime") def test_generate_job_info_default(self, mock_datetime): mock_datetime.now.return_value = datetime(2023, 5, 1, 12, 0, 0) - result = jobs.generate_job_info( self.t_mock, self.app_name, self.input_uri, self.input_file ) - self.assertEqual(result["name"], f"{self.app_name}_20230501_120000") self.assertEqual(result["appId"], self.app_name) self.assertEqual(result["appVersion"], "1.0") @@ -46,7 +43,7 @@ def test_generate_job_info_default(self, mock_datetime): result["parameterSet"]["appArgs"], [{"name": "Input Script", "arg": self.input_file}], ) - self.assertEqual(result["parameterSet"]["schedulerOptions"], []) + self.assertNotIn("schedulerOptions", result["parameterSet"]) def test_generate_job_info_custom(self): custom_job_name = "custom-job" @@ -55,7 +52,6 @@ def test_generate_job_info_custom(self): custom_cores_per_node = 4 custom_queue = "high-priority" custom_allocation = "project123" - result = jobs.generate_job_info( self.t_mock, self.app_name, @@ -68,7 +64,6 @@ def test_generate_job_info_custom(self): queue=custom_queue, allocation=custom_allocation, ) - self.assertEqual(result["name"], custom_job_name) self.assertEqual(result["maxMinutes"], custom_max_minutes) self.assertEqual(result["nodeCount"], custom_node_count) @@ -81,12 +76,24 @@ def test_generate_job_info_custom(self): def test_generate_job_info_invalid_app(self): self.t_mock.apps.getAppLatestVersion.side_effect = Exception("Invalid app") - with self.assertRaises(Exception): jobs.generate_job_info( self.t_mock, "invalid-app", self.input_uri, self.input_file ) + def test_generate_job_info_opensees(self): + opensees_app_name = "opensees-express" + result = jobs.generate_job_info( + self.t_mock, opensees_app_name, self.input_uri, self.input_file + ) + self.assertIn("parameterSet", result) + self.assertIn("envVariables", result["parameterSet"]) + self.assertEqual( + result["parameterSet"]["envVariables"], + [{"key": "tclScript", "value": self.input_file}], + ) + self.assertNotIn("appArgs", result["parameterSet"]) + if __name__ == "__main__": unittest.main()