lsst-ctrl-bps-panda 29.2025.2100__tar.gz → 29.2025.2300__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {lsst_ctrl_bps_panda-29.2025.2100/python/lsst_ctrl_bps_panda.egg-info → lsst_ctrl_bps_panda-29.2025.2300}/PKG-INFO +1 -1
  2. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/panda_service.py +41 -0
  3. lsst_ctrl_bps_panda-29.2025.2300/python/lsst/ctrl/bps/panda/version.py +2 -0
  4. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300/python/lsst_ctrl_bps_panda.egg-info}/PKG-INFO +1 -1
  5. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst_ctrl_bps_panda.egg-info/SOURCES.txt +1 -0
  6. lsst_ctrl_bps_panda-29.2025.2300/tests/test_panda_service.py +194 -0
  7. lsst_ctrl_bps_panda-29.2025.2100/python/lsst/ctrl/bps/panda/version.py +0 -2
  8. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/COPYRIGHT +0 -0
  9. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/LICENSE +0 -0
  10. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/README.rst +0 -0
  11. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/bsd_license.txt +0 -0
  12. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/gpl-v3.0.txt +0 -0
  13. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/pyproject.toml +0 -0
  14. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/__init__.py +0 -0
  15. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/cli/__init__.py +0 -0
  16. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/cli/cmd/__init__.py +0 -0
  17. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/cli/cmd/panda_auth_commands.py +0 -0
  18. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/cli/panda_auth.py +0 -0
  19. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/cmd_line_embedder.py +0 -0
  20. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/conf_example/example_panda_SLAC.yaml +0 -0
  21. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/conf_example/pipelines_check_idf.yaml +0 -0
  22. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/conf_example/test_idf.yaml +0 -0
  23. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/conf_example/test_sdf.yaml +0 -0
  24. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/conf_example/test_usdf.yaml +0 -0
  25. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/constants.py +0 -0
  26. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/edgenode/__init__.py +0 -0
  27. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/edgenode/build_cmd_line_decoder.py +0 -0
  28. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/edgenode/cmd_line_decoder.py +0 -0
  29. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/panda_auth_drivers.py +0 -0
  30. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/panda_auth_utils.py +0 -0
  31. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst/ctrl/bps/panda/utils.py +0 -0
  32. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst_ctrl_bps_panda.egg-info/dependency_links.txt +0 -0
  33. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst_ctrl_bps_panda.egg-info/requires.txt +0 -0
  34. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst_ctrl_bps_panda.egg-info/top_level.txt +0 -0
  35. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/python/lsst_ctrl_bps_panda.egg-info/zip-safe +0 -0
  36. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/setup.cfg +0 -0
  37. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/tests/test_cmd_line_embedder.py +0 -0
  38. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/tests/test_panda_auth_utils.py +0 -0
  39. {lsst_ctrl_bps_panda-29.2025.2100 → lsst_ctrl_bps_panda-29.2025.2300}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-ctrl-bps-panda
3
- Version: 29.2025.2100
3
+ Version: 29.2025.2300
4
4
  Summary: PanDA plugin for lsst-ctrl-bps.
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License: BSD 3-Clause License
@@ -379,6 +379,47 @@ class PanDAService(BaseWmsService):
379
379
  if status != 0:
380
380
  raise RuntimeError(message)
381
381
 
382
+ def get_status(
383
+ self,
384
+ wms_workflow_id=None,
385
+ hist=0,
386
+ is_global=False,
387
+ ):
388
+ # Docstring inherited from BaseWmsService.get_status.
389
+
390
+ idds_client = get_idds_client(self.config)
391
+ ret = idds_client.get_requests(request_id=wms_workflow_id, with_detail=False)
392
+ _LOG.debug("PanDA get workflow status returned = %s", str(ret))
393
+
394
+ request_status = ret[0]
395
+ if request_status != 0:
396
+ state = WmsStates.UNKNOWN
397
+ message = f"Error getting workflow status for id {wms_workflow_id}: ret = {ret}"
398
+ else:
399
+ tasks = ret[1][1]
400
+ if not tasks:
401
+ state = WmsStates.UNKNOWN
402
+ message = f"No records found for workflow id '{wms_workflow_id}'. Hint: double check the id"
403
+ elif not isinstance(tasks[0], dict):
404
+ state = WmsStates.UNKNOWN
405
+ message = f"Error getting workflow status for id {wms_workflow_id}: ret = {ret}"
406
+ else:
407
+ message = ""
408
+ head = tasks[0]
409
+ workflow_status = head["status"]["attributes"]["_name_"]
410
+ if workflow_status in ["Finished"]:
411
+ state = WmsStates.SUCCEEDED
412
+ elif workflow_status in ["Failed", "Expired", "SubFinished"]:
413
+ state = WmsStates.FAILED
414
+ elif workflow_status in ["Cancelled"]:
415
+ state = WmsStates.DELETED
416
+ elif workflow_status in ["Suspended"]:
417
+ state = WmsStates.HELD
418
+ else:
419
+ state = WmsStates.RUNNING
420
+
421
+ return state, message
422
+
382
423
 
383
424
  class PandaBpsWmsWorkflow(BaseWmsWorkflow):
384
425
  """A single Panda based workflow.
@@ -0,0 +1,2 @@
1
+ __all__ = ["__version__"]
2
+ __version__ = "29.2025.2300"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-ctrl-bps-panda
3
- Version: 29.2025.2100
3
+ Version: 29.2025.2300
4
4
  Summary: PanDA plugin for lsst-ctrl-bps.
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License: BSD 3-Clause License
@@ -33,4 +33,5 @@ python/lsst_ctrl_bps_panda.egg-info/top_level.txt
33
33
  python/lsst_ctrl_bps_panda.egg-info/zip-safe
34
34
  tests/test_cmd_line_embedder.py
35
35
  tests/test_panda_auth_utils.py
36
+ tests/test_panda_service.py
36
37
  tests/test_utils.py
@@ -0,0 +1,194 @@
1
+ # This file is part of ctrl_bps_panda.
2
+ #
3
+ # Developed for the LSST Data Management System.
4
+ # This product includes software developed by the LSST Project
5
+ # (https://www.lsst.org).
6
+ # See the COPYRIGHT file at the top-level directory of this distribution
7
+ # for details of code ownership.
8
+ #
9
+ # This software is dual licensed under the GNU General Public License and also
10
+ # under a 3-clause BSD license. Recipients may choose which of these licenses
11
+ # to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12
+ # respectively. If you choose the GPL option then the following text applies
13
+ # (but note that there is still no warranty even if you opt for BSD instead):
14
+ #
15
+ # This program is free software: you can redistribute it and/or modify
16
+ # it under the terms of the GNU General Public License as published by
17
+ # the Free Software Foundation, either version 3 of the License, or
18
+ # (at your option) any later version.
19
+ #
20
+ # This program is distributed in the hope that it will be useful,
21
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
+ # GNU General Public License for more details.
24
+ #
25
+ # You should have received a copy of the GNU General Public License
26
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
27
+
28
+ """Unit tests for ctrl_bps_panda panda_service module."""
29
+
30
+ import logging
31
+ import unittest
32
+
33
+ from idds.common.constants import WorkStatus
34
+
35
+ from lsst.ctrl.bps import BpsConfig, WmsStates
36
+ from lsst.ctrl.bps.panda import panda_service
37
+
38
+ _LOG = logging.getLogger(__name__)
39
+
40
+
41
+ class MockClient:
42
+ """Mock idds client."""
43
+
44
+ def __init__(self):
45
+ _LOG.debug("Called mock client init")
46
+
47
+ def get_requests(self, request_id, with_detail):
48
+ _LOG.debug("Called mock client get_requests with %s", request_id)
49
+ status = None
50
+ match request_id:
51
+ case "1000": # GetRequestsFailure
52
+ requests = (1, "PanDA error message")
53
+ case "1001":
54
+ status = WorkStatus.Finished
55
+ case "1002":
56
+ status = WorkStatus.SubFinished
57
+ case "1003":
58
+ status = WorkStatus.Failed
59
+ case "1004":
60
+ status = WorkStatus.Cancelled
61
+ case "1005":
62
+ status = WorkStatus.Suspended
63
+ case "1006":
64
+ status = WorkStatus.Running
65
+ case "1007":
66
+ status = WorkStatus.Transforming
67
+ case "1008":
68
+ requests = (0, [True, [False, "An unknown IDDS exception occurred."]])
69
+ case _: # Unknown ID
70
+ requests = (0, [True, []])
71
+
72
+ if status:
73
+ workflow_name = "FAKE_WORKFLOW_NAME_20250515T213417Z"
74
+ requests = (
75
+ 0,
76
+ [
77
+ True,
78
+ [
79
+ {
80
+ "name": workflow_name,
81
+ "request_id": request_id,
82
+ "status": {
83
+ "attributes": {
84
+ "_value_": status.value,
85
+ "_name_": status.name,
86
+ "_sort_order_": status.value,
87
+ }
88
+ },
89
+ }
90
+ ],
91
+ ],
92
+ )
93
+
94
+ return requests
95
+
96
+
97
+ class TestPanDAService(unittest.TestCase):
98
+ """Test PanDAService class methods."""
99
+
100
+ def setUp(self):
101
+ config = BpsConfig({}, wms_service_class_fqn="lsst.ctrl.bps.panda.PanDAService")
102
+ self.service = panda_service.PanDAService(config)
103
+
104
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
105
+ def testGetStatusGetRequestsFailure(self, mock_get):
106
+ mock_get.return_value = MockClient()
107
+ status, message = self.service.get_status("1000")
108
+
109
+ self.assertEqual(status, WmsStates.UNKNOWN)
110
+ self.assertEqual(
111
+ message, "Error getting workflow status for id 1000: ret = (1, 'PanDA error message')"
112
+ )
113
+
114
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
115
+ def testGetStatusUnknownID(self, mock_get):
116
+ mock_get.return_value = MockClient()
117
+ status, message = self.service.get_status("9999")
118
+
119
+ self.assertEqual(status, WmsStates.UNKNOWN)
120
+ self.assertEqual(message, "No records found for workflow id '9999'. Hint: double check the id")
121
+
122
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
123
+ def testGetStatusFinished(self, mock_get):
124
+ mock_get.return_value = MockClient()
125
+ status, message = self.service.get_status("1001")
126
+
127
+ self.assertEqual(status, WmsStates.SUCCEEDED)
128
+ self.assertEqual(message, "")
129
+
130
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
131
+ def testGetStatusSubFinished(self, mock_get):
132
+ mock_get.return_value = MockClient()
133
+ status, message = self.service.get_status("1002")
134
+
135
+ self.assertEqual(status, WmsStates.FAILED)
136
+ self.assertEqual(message, "")
137
+
138
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
139
+ def testGetStatusFailed(self, mock_get):
140
+ mock_get.return_value = MockClient()
141
+ status, message = self.service.get_status("1003")
142
+
143
+ self.assertEqual(status, WmsStates.FAILED)
144
+ self.assertEqual(message, "")
145
+
146
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
147
+ def testGetStatusCancelled(self, mock_get):
148
+ mock_get.return_value = MockClient()
149
+ status, message = self.service.get_status("1004")
150
+
151
+ self.assertEqual(status, WmsStates.DELETED)
152
+ self.assertEqual(message, "")
153
+
154
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
155
+ def testGetStatusSuspended(self, mock_get):
156
+ mock_get.return_value = MockClient()
157
+ status, message = self.service.get_status("1005")
158
+
159
+ self.assertEqual(status, WmsStates.HELD)
160
+ self.assertEqual(message, "")
161
+
162
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
163
+ def testGetStatusRunning(self, mock_get):
164
+ mock_get.return_value = MockClient()
165
+ status, message = self.service.get_status("1006")
166
+
167
+ self.assertEqual(status, WmsStates.RUNNING)
168
+ self.assertEqual(message, "")
169
+
170
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
171
+ def testGetStatusTransforming(self, mock_get):
172
+ mock_get.return_value = MockClient()
173
+ status, message = self.service.get_status("1007")
174
+
175
+ self.assertEqual(status, WmsStates.RUNNING)
176
+ self.assertEqual(message, "")
177
+
178
+ @unittest.mock.patch("lsst.ctrl.bps.panda.panda_service.get_idds_client")
179
+ def testGetStatusUnknownIDDSException(self, mock_get):
180
+ # Test example unknown IDDS exception similar to what occurs
181
+ # if give path to ctrl_bps_panda's get_status.
182
+ mock_get.return_value = MockClient()
183
+ status, message = self.service.get_status("1008")
184
+
185
+ self.assertEqual(status, WmsStates.UNKNOWN)
186
+ self.assertEqual(
187
+ message,
188
+ "Error getting workflow status for id 1008: ret = "
189
+ "(0, [True, [False, 'An unknown IDDS exception occurred.']])",
190
+ )
191
+
192
+
193
+ if __name__ == "__main__":
194
+ unittest.main()
@@ -1,2 +0,0 @@
1
- __all__ = ["__version__"]
2
- __version__ = "29.2025.2100"