lsst-ctrl-execute 28.2025.500__py3-none-any.whl
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.
- lsst/__init__.py +3 -0
- lsst/ctrl/__init__.py +3 -0
- lsst/ctrl/execute/__init__.py +27 -0
- lsst/ctrl/execute/allocationConfig.py +69 -0
- lsst/ctrl/execute/allocator.py +474 -0
- lsst/ctrl/execute/allocatorParser.py +230 -0
- lsst/ctrl/execute/condorConfig.py +75 -0
- lsst/ctrl/execute/condorInfoConfig.py +65 -0
- lsst/ctrl/execute/envString.py +50 -0
- lsst/ctrl/execute/findPackageFile.py +107 -0
- lsst/ctrl/execute/libexec/allocateNodes.py +93 -0
- lsst/ctrl/execute/libexec/dagIdInfo.py +60 -0
- lsst/ctrl/execute/libexec/qdelete.py +48 -0
- lsst/ctrl/execute/libexec/qstatus.py +59 -0
- lsst/ctrl/execute/namedClassFactory.py +57 -0
- lsst/ctrl/execute/pbsPlugin.py +124 -0
- lsst/ctrl/execute/qCommand.py +66 -0
- lsst/ctrl/execute/seqFile.py +64 -0
- lsst/ctrl/execute/slurmPlugin.py +488 -0
- lsst/ctrl/execute/templateWriter.py +50 -0
- lsst_ctrl_execute-28.2025.500.dist-info/METADATA +20 -0
- lsst_ctrl_execute-28.2025.500.dist-info/RECORD +24 -0
- lsst_ctrl_execute-28.2025.500.dist-info/WHEEL +4 -0
- lsst_ctrl_execute-28.2025.500.dist-info/entry_points.txt +5 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# LSST Data Management System
|
|
5
|
+
# Copyright 2008-2016 LSST Corporation.
|
|
6
|
+
#
|
|
7
|
+
# This product includes software developed by the
|
|
8
|
+
# LSST Project (http://www.lsst.org/).
|
|
9
|
+
#
|
|
10
|
+
# This program is free software: you can redistribute it and/or modify
|
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
|
12
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
13
|
+
# (at your option) any later version.
|
|
14
|
+
#
|
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
18
|
+
# GNU General Public License for more details.
|
|
19
|
+
#
|
|
20
|
+
# You should have received a copy of the LSST License Statement and
|
|
21
|
+
# the GNU General Public License along with this program. If not,
|
|
22
|
+
# see <http://www.lsstcorp.org/LegalNotices/>.
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
import argparse
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class AllocatorParser:
|
|
29
|
+
"""An argument parser for node allocation requests.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
basename : `str`
|
|
34
|
+
The name used to identify the running program
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, basename):
|
|
38
|
+
"""Construct an AllocatorParser
|
|
39
|
+
@param argv: list containing the command line arguments
|
|
40
|
+
@return: the parser options and remaining arguments
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
self.defaults = {}
|
|
44
|
+
self.args = self.parseArgs(basename)
|
|
45
|
+
|
|
46
|
+
def parseArgs(self, basename) -> argparse.Namespace:
|
|
47
|
+
"""Parse command line, and test for required arguments
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
argv: `list`
|
|
52
|
+
list of strings containing the command line arguments
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
The parser options and remaining arguments
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
parser = argparse.ArgumentParser(prog=basename)
|
|
60
|
+
parser.add_argument(
|
|
61
|
+
"platform", type=str, default="s3df", help="node allocation platform"
|
|
62
|
+
)
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"--auto",
|
|
65
|
+
action="store_true",
|
|
66
|
+
dest="auto",
|
|
67
|
+
help="use automatic detection of jobs to determine glide-ins",
|
|
68
|
+
)
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
"-n",
|
|
71
|
+
"--node-count",
|
|
72
|
+
action="store",
|
|
73
|
+
default=None,
|
|
74
|
+
dest="nodeCount",
|
|
75
|
+
help="number of glideins to submit; these are chunks of a node, size the number of cores/cpus",
|
|
76
|
+
type=int,
|
|
77
|
+
required=True,
|
|
78
|
+
)
|
|
79
|
+
parser.add_argument(
|
|
80
|
+
"-c",
|
|
81
|
+
"--cpus",
|
|
82
|
+
action="store",
|
|
83
|
+
default=16,
|
|
84
|
+
dest="cpus",
|
|
85
|
+
help="cores / cpus per glidein",
|
|
86
|
+
type=int,
|
|
87
|
+
required=False,
|
|
88
|
+
)
|
|
89
|
+
parser.add_argument(
|
|
90
|
+
"-a",
|
|
91
|
+
"--account",
|
|
92
|
+
action="store",
|
|
93
|
+
default="rubin:developers",
|
|
94
|
+
dest="account",
|
|
95
|
+
help="Slurm account for glidein job",
|
|
96
|
+
type=str,
|
|
97
|
+
)
|
|
98
|
+
parser.add_argument(
|
|
99
|
+
"--collector",
|
|
100
|
+
action="store",
|
|
101
|
+
default=None,
|
|
102
|
+
dest="collector",
|
|
103
|
+
help="machine name of nondefault htcondor collector",
|
|
104
|
+
type=str,
|
|
105
|
+
required=False,
|
|
106
|
+
)
|
|
107
|
+
parser.add_argument(
|
|
108
|
+
"--collector-port",
|
|
109
|
+
action="store",
|
|
110
|
+
default=9618,
|
|
111
|
+
dest="collectorport",
|
|
112
|
+
help="port used for nondefault htcondor collector",
|
|
113
|
+
type=int,
|
|
114
|
+
required=False,
|
|
115
|
+
)
|
|
116
|
+
parser.add_argument(
|
|
117
|
+
"-s",
|
|
118
|
+
"--qos",
|
|
119
|
+
action="store",
|
|
120
|
+
default=None,
|
|
121
|
+
dest="qos",
|
|
122
|
+
help="Slurm qos for glidein job",
|
|
123
|
+
type=str,
|
|
124
|
+
)
|
|
125
|
+
parser.add_argument(
|
|
126
|
+
"-m",
|
|
127
|
+
"--maximum-wall-clock",
|
|
128
|
+
action="store",
|
|
129
|
+
dest="maximumWallClock",
|
|
130
|
+
default=None,
|
|
131
|
+
help="maximum wall clock time; e.g., 3600, 10:00:00, 6-00:00:00, etc",
|
|
132
|
+
type=str,
|
|
133
|
+
required=True,
|
|
134
|
+
)
|
|
135
|
+
parser.add_argument(
|
|
136
|
+
"-q",
|
|
137
|
+
"--queue",
|
|
138
|
+
action="store",
|
|
139
|
+
dest="queue",
|
|
140
|
+
default="roma,milano",
|
|
141
|
+
help="queue / partition name",
|
|
142
|
+
)
|
|
143
|
+
parser.add_argument(
|
|
144
|
+
"-O",
|
|
145
|
+
"--output-log",
|
|
146
|
+
action="store",
|
|
147
|
+
dest="outputLog",
|
|
148
|
+
default=None,
|
|
149
|
+
help="Output log filename; this option for PBS, unused with Slurm",
|
|
150
|
+
)
|
|
151
|
+
parser.add_argument(
|
|
152
|
+
"-E",
|
|
153
|
+
"--error-log",
|
|
154
|
+
action="store",
|
|
155
|
+
dest="errorLog",
|
|
156
|
+
default=None,
|
|
157
|
+
help="Error log filename; this option for PBS, unused with Slurm",
|
|
158
|
+
)
|
|
159
|
+
parser.add_argument(
|
|
160
|
+
"-g",
|
|
161
|
+
"--glidein-shutdown",
|
|
162
|
+
action="store",
|
|
163
|
+
dest="glideinShutdown",
|
|
164
|
+
type=int,
|
|
165
|
+
default=None,
|
|
166
|
+
help="glide-in inactivity shutdown time in seconds",
|
|
167
|
+
)
|
|
168
|
+
parser.add_argument(
|
|
169
|
+
"--openfiles",
|
|
170
|
+
action="store",
|
|
171
|
+
dest="openfiles",
|
|
172
|
+
type=int,
|
|
173
|
+
default=20480,
|
|
174
|
+
help="set the limit on number of open files (fd) per process",
|
|
175
|
+
)
|
|
176
|
+
parser.add_argument(
|
|
177
|
+
"-p",
|
|
178
|
+
"--pack",
|
|
179
|
+
action="store_true",
|
|
180
|
+
dest="packnodes",
|
|
181
|
+
help="encourage nodes to pack jobs rather than spread",
|
|
182
|
+
)
|
|
183
|
+
parser.add_argument(
|
|
184
|
+
"-v", "--verbose", action="store_true", dest="verbose", help="verbose"
|
|
185
|
+
)
|
|
186
|
+
parser.add_argument(
|
|
187
|
+
"-r",
|
|
188
|
+
"--reservation",
|
|
189
|
+
action="store",
|
|
190
|
+
dest="reservation",
|
|
191
|
+
default=None,
|
|
192
|
+
help="target a particular Slurm reservation",
|
|
193
|
+
)
|
|
194
|
+
parser.add_argument(
|
|
195
|
+
"-d",
|
|
196
|
+
"--dynamic",
|
|
197
|
+
const="__default__",
|
|
198
|
+
nargs="?",
|
|
199
|
+
action="store",
|
|
200
|
+
dest="dynamic",
|
|
201
|
+
type=str,
|
|
202
|
+
default="__default__",
|
|
203
|
+
help="configure to use dynamic/partitionable slot; legacy option: this is always enabled now",
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
self.args = parser.parse_args()
|
|
207
|
+
|
|
208
|
+
return self.args
|
|
209
|
+
|
|
210
|
+
def getArgs(self):
|
|
211
|
+
"""Accessor method to get arguments left after standard parsed options
|
|
212
|
+
are initialized.
|
|
213
|
+
|
|
214
|
+
Returns
|
|
215
|
+
-------
|
|
216
|
+
args: `argparse.Namespace`
|
|
217
|
+
remaining command line arguments
|
|
218
|
+
"""
|
|
219
|
+
return self.args
|
|
220
|
+
|
|
221
|
+
def getPlatform(self):
|
|
222
|
+
"""Accessor method to retrieve the "platform" that was specified on
|
|
223
|
+
the command line.
|
|
224
|
+
|
|
225
|
+
Returns
|
|
226
|
+
-------
|
|
227
|
+
platform: `str`
|
|
228
|
+
the name of the "platform"
|
|
229
|
+
"""
|
|
230
|
+
return self.args.platform
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# LSST Data Management System
|
|
5
|
+
# Copyright 2008-2016 LSST Corporation.
|
|
6
|
+
#
|
|
7
|
+
# This product includes software developed by the
|
|
8
|
+
# LSST Project (http://www.lsst.org/).
|
|
9
|
+
#
|
|
10
|
+
# This program is free software: you can redistribute it and/or modify
|
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
|
12
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
13
|
+
# (at your option) any later version.
|
|
14
|
+
#
|
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
18
|
+
# GNU General Public License for more details.
|
|
19
|
+
#
|
|
20
|
+
# You should have received a copy of the LSST License Statement and
|
|
21
|
+
# the GNU General Public License along with this program. If not,
|
|
22
|
+
# see <http://www.lsstcorp.org/LegalNotices/>.
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
import lsst.pex.config as pexConfig
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class PlatformConfig(pexConfig.Config):
|
|
29
|
+
"""Platform specific information"""
|
|
30
|
+
|
|
31
|
+
defaultRoot = pexConfig.Field(
|
|
32
|
+
doc="remote root for working directories", dtype=str, default=None
|
|
33
|
+
)
|
|
34
|
+
localScratch = pexConfig.Field(
|
|
35
|
+
doc="local Condor scratch directory", dtype=str, default=None
|
|
36
|
+
)
|
|
37
|
+
idsPerJob = pexConfig.Field(
|
|
38
|
+
doc="number of ids to work on per job", dtype=int, default=1
|
|
39
|
+
)
|
|
40
|
+
dataDirectory = pexConfig.Field(
|
|
41
|
+
doc="remote directory where date that jobs will use is kept",
|
|
42
|
+
dtype=str,
|
|
43
|
+
default=None,
|
|
44
|
+
)
|
|
45
|
+
fileSystemDomain = pexConfig.Field(
|
|
46
|
+
doc="network domain name of remote system", dtype=str, default=None
|
|
47
|
+
)
|
|
48
|
+
eupsPath = pexConfig.Field(
|
|
49
|
+
doc="location of remote EUPS stack", dtype=str, default=None
|
|
50
|
+
)
|
|
51
|
+
nodeSetRequired = pexConfig.Field(
|
|
52
|
+
doc="is the nodeset required", dtype=bool, default=False
|
|
53
|
+
)
|
|
54
|
+
scheduler = pexConfig.Field(doc="scheduler type", dtype=str, default=None)
|
|
55
|
+
manager = pexConfig.Field(doc="workflow manager", dtype=str, default=None)
|
|
56
|
+
setup_using = pexConfig.Field(doc="environment setup type", dtype=str, default=None)
|
|
57
|
+
manager_software_home = pexConfig.Field(
|
|
58
|
+
doc="location of workflow manager software", dtype=str, default=None
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class CondorConfig(pexConfig.Config):
|
|
63
|
+
"""A pex_config file describing the platform specific information required
|
|
64
|
+
to fill out templates for running ctrl_orca jobs
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
platform = pexConfig.ConfigField("platform configuration", PlatformConfig)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class FakeTypeMap(dict):
|
|
71
|
+
def __init__(self, configClass):
|
|
72
|
+
self.configClass = configClass
|
|
73
|
+
|
|
74
|
+
def __getitem__(self, k):
|
|
75
|
+
return self.setdefault(k, self.configClass)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# LSST Data Management System
|
|
5
|
+
# Copyright 2008-2016 LSST Corporation.
|
|
6
|
+
#
|
|
7
|
+
# This product includes software developed by the
|
|
8
|
+
# LSST Project (http://www.lsst.org/).
|
|
9
|
+
#
|
|
10
|
+
# This program is free software: you can redistribute it and/or modify
|
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
|
12
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
13
|
+
# (at your option) any later version.
|
|
14
|
+
#
|
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
18
|
+
# GNU General Public License for more details.
|
|
19
|
+
#
|
|
20
|
+
# You should have received a copy of the LSST License Statement and
|
|
21
|
+
# the GNU General Public License along with this program. If not,
|
|
22
|
+
# see <http://www.lsstcorp.org/LegalNotices/>.
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
import lsst.pex.config as pexConfig
|
|
26
|
+
from lsst.ctrl.execute.findPackageFile import find_package_file
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class FakeTypeMap(dict):
|
|
30
|
+
def __init__(self, configClass):
|
|
31
|
+
self.configClass = configClass
|
|
32
|
+
|
|
33
|
+
def __getitem__(self, k):
|
|
34
|
+
return self.setdefault(k, self.configClass)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class UserInfoConfig(pexConfig.Config):
|
|
38
|
+
"""User information"""
|
|
39
|
+
|
|
40
|
+
name = pexConfig.Field(doc="user login name", dtype=str, default=None)
|
|
41
|
+
home = pexConfig.Field(doc="user home directory", dtype=str, default=None)
|
|
42
|
+
scratch = pexConfig.Field(doc="user scratch directory", dtype=str, default=None)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class UserConfig(pexConfig.Config):
|
|
46
|
+
"""User specific information"""
|
|
47
|
+
|
|
48
|
+
user = pexConfig.ConfigField(doc="user", dtype=UserInfoConfig)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class CondorInfoConfig(pexConfig.Config):
|
|
52
|
+
"""A pex_config file describing the platform specific information about
|
|
53
|
+
remote user logins.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
platform = pexConfig.ConfigChoiceField("platform info", FakeTypeMap(UserConfig))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__":
|
|
60
|
+
config = CondorInfoConfig()
|
|
61
|
+
filename = find_package_file("condor-info.py")
|
|
62
|
+
config.loadFromStream(filename.read())
|
|
63
|
+
|
|
64
|
+
for i in config.platform:
|
|
65
|
+
print(i)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# LSST Data Management System
|
|
5
|
+
# Copyright 2008-2016 LSST Corporation.
|
|
6
|
+
#
|
|
7
|
+
# This product includes software developed by the
|
|
8
|
+
# LSST Project (http://www.lsst.org/).
|
|
9
|
+
#
|
|
10
|
+
# This program is free software: you can redistribute it and/or modify
|
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
|
12
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
13
|
+
# (at your option) any later version.
|
|
14
|
+
#
|
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
18
|
+
# GNU General Public License for more details.
|
|
19
|
+
#
|
|
20
|
+
# You should have received a copy of the LSST License Statement and
|
|
21
|
+
# the GNU General Public License along with this program. If not,
|
|
22
|
+
# see <http://www.lsstcorp.org/LegalNotices/>.
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
import os
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def resolve(input: str) -> str:
|
|
29
|
+
"""Render a string with any `$`-prefixed words substituted with a matching
|
|
30
|
+
environment variable.
|
|
31
|
+
|
|
32
|
+
.. deprecated:: w.2025.05
|
|
33
|
+
`lsst.ctrl.execute.envString.resolve` is deprecated and no longer used
|
|
34
|
+
by any internal APIs because `lsst.resource.ResourcePath` handles
|
|
35
|
+
environment variable expansion.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
input : `str`
|
|
40
|
+
A string containing environment variables to resolve.
|
|
41
|
+
|
|
42
|
+
Raises
|
|
43
|
+
------
|
|
44
|
+
RuntimeError
|
|
45
|
+
If the environment variable does not exist
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
if "$" in (retVal := os.path.expandvars(input)):
|
|
49
|
+
raise RuntimeError(f"couldn't resolve all environment variables in {retVal}")
|
|
50
|
+
return retVal
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# LSST Data Management System
|
|
5
|
+
# Copyright 2008-2016 LSST Corporation.
|
|
6
|
+
#
|
|
7
|
+
# This product includes software developed by the
|
|
8
|
+
# LSST Project (http://www.lsst.org/).
|
|
9
|
+
#
|
|
10
|
+
# This program is free software: you can redistribute it and/or modify
|
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
|
12
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
13
|
+
# (at your option) any later version.
|
|
14
|
+
#
|
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
18
|
+
# GNU General Public License for more details.
|
|
19
|
+
#
|
|
20
|
+
# You should have received a copy of the LSST License Statement and
|
|
21
|
+
# the GNU General Public License along with this program. If not,
|
|
22
|
+
# see <http://www.lsstcorp.org/LegalNotices/>.
|
|
23
|
+
#
|
|
24
|
+
import os
|
|
25
|
+
import sys
|
|
26
|
+
|
|
27
|
+
import lsst.utils
|
|
28
|
+
from lsst.resources import ResourcePath
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def find_package_file(
|
|
32
|
+
filename: str, kind: str = "config", platform: str | None = None
|
|
33
|
+
) -> ResourcePath:
|
|
34
|
+
"""Find a package file from a set of candidate locations.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
filename : `str`
|
|
39
|
+
The unqualified name of a file to locate.
|
|
40
|
+
|
|
41
|
+
kind : `str`
|
|
42
|
+
The name of a subdirectory in which to look for the file within a
|
|
43
|
+
package location, relative to an ``etc/`` directory.
|
|
44
|
+
|
|
45
|
+
platform : `str` | `None`
|
|
46
|
+
The name of a platform plugin in which to look for the file, or `None`
|
|
47
|
+
if no platform plugin should be searched.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
`lsst.resources.ResourcePath`
|
|
52
|
+
|
|
53
|
+
Raises
|
|
54
|
+
------
|
|
55
|
+
FileNotFoundError
|
|
56
|
+
If a requested file object cannot be located in the candidate hierarchy
|
|
57
|
+
|
|
58
|
+
Notes
|
|
59
|
+
-----
|
|
60
|
+
The candidate locations are, in descending order of preference:
|
|
61
|
+
- An ``.lsst`` directory in the user's home directory.
|
|
62
|
+
- An ``lsst`` directory in the user's ``$XDG_CONFIG_HOME`` directory
|
|
63
|
+
- An ``etc/{kind}`` directory in the EUPS stack environment for the
|
|
64
|
+
platform.
|
|
65
|
+
- An ``etc/{kind}`` directory in the current Python environment/venv shared
|
|
66
|
+
data directory.
|
|
67
|
+
- An ``etc/{kind}`` directory in an installed ``lsst.ctrl.platform.*``
|
|
68
|
+
package.
|
|
69
|
+
- An ``etc/{kind}`` directory in the ``lsst.ctrl.execute`` package.
|
|
70
|
+
"""
|
|
71
|
+
# If the path, after expansion, is absolute, we don't need to go looking
|
|
72
|
+
# for it, it should be exactly where it is.
|
|
73
|
+
if (_filename := ResourcePath(filename, forceAbsolute=False)).isabs():
|
|
74
|
+
return _filename
|
|
75
|
+
|
|
76
|
+
home_dir = os.getenv("HOME", "~")
|
|
77
|
+
xdg_config_home = os.getenv("XDG_CONFIG_HOME", "~/.config")
|
|
78
|
+
try:
|
|
79
|
+
platform_pkg_dir = lsst.utils.getPackageDir(f"ctrl_platform_{platform}")
|
|
80
|
+
except (LookupError, ValueError):
|
|
81
|
+
platform_pkg_dir = None
|
|
82
|
+
|
|
83
|
+
file_candidates = [
|
|
84
|
+
ResourcePath(home_dir).join(".lsst").join(_filename),
|
|
85
|
+
ResourcePath(xdg_config_home).join("lsst").join(_filename),
|
|
86
|
+
(
|
|
87
|
+
ResourcePath(platform_pkg_dir).join("etc").join(kind).join(_filename)
|
|
88
|
+
if platform_pkg_dir
|
|
89
|
+
else None
|
|
90
|
+
),
|
|
91
|
+
ResourcePath(sys.exec_prefix).join("etc").join(kind).join(_filename),
|
|
92
|
+
(
|
|
93
|
+
ResourcePath(
|
|
94
|
+
f"resource://lsst.ctrl.platform.{platform}/etc/{kind}/{_filename}"
|
|
95
|
+
)
|
|
96
|
+
if platform
|
|
97
|
+
else None
|
|
98
|
+
),
|
|
99
|
+
ResourcePath(f"resource://lsst.ctrl.execute/etc/{kind}/{_filename}"),
|
|
100
|
+
]
|
|
101
|
+
try:
|
|
102
|
+
found_file: ResourcePath = [
|
|
103
|
+
c for c in file_candidates if c is not None and c.exists()
|
|
104
|
+
][0]
|
|
105
|
+
except IndexError:
|
|
106
|
+
raise FileNotFoundError(f"No file {filename} found in package file lookup")
|
|
107
|
+
return found_file
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# LSST Data Management System
|
|
5
|
+
# Copyright 2008-2016 LSST Corporation.
|
|
6
|
+
#
|
|
7
|
+
# This product includes software developed by the
|
|
8
|
+
# LSST Project (http://www.lsst.org/).
|
|
9
|
+
#
|
|
10
|
+
# This program is free software: you can redistribute it and/or modify
|
|
11
|
+
# it under the terms of the GNU General Public License as published by
|
|
12
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
13
|
+
# (at your option) any later version.
|
|
14
|
+
#
|
|
15
|
+
# This program is distributed in the hope that it will be useful,
|
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
18
|
+
# GNU General Public License for more details.
|
|
19
|
+
#
|
|
20
|
+
# You should have received a copy of the LSST License Statement and
|
|
21
|
+
# the GNU General Public License along with this program. If not,
|
|
22
|
+
# see <http://www.lsstcorp.org/LegalNotices/>.
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
import logging
|
|
26
|
+
import sys
|
|
27
|
+
from typing import Any
|
|
28
|
+
|
|
29
|
+
from lsst.ctrl.execute.allocator import Allocator
|
|
30
|
+
from lsst.ctrl.execute.allocatorParser import AllocatorParser
|
|
31
|
+
from lsst.ctrl.execute.condorConfig import CondorConfig
|
|
32
|
+
from lsst.ctrl.execute.findPackageFile import find_package_file
|
|
33
|
+
from lsst.ctrl.execute.namedClassFactory import NamedClassFactory
|
|
34
|
+
|
|
35
|
+
_LOG = logging.getLogger("lsst.ctrl.execute")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def setup_logging(options: dict[str, Any] | None = None) -> None:
|
|
39
|
+
"""Configure logger.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
options : dict[str, Any]
|
|
44
|
+
Logger settings. The key/value pairs it contains will be used to
|
|
45
|
+
override corresponding default settings. If empty or None (default),
|
|
46
|
+
logger will be set up with default settings.
|
|
47
|
+
"""
|
|
48
|
+
settings = {
|
|
49
|
+
"datefmt": "%Y-%m-%dT%H:%M:%S%z",
|
|
50
|
+
"format": "%(levelname)s %(asctime)s %(name)s - %(message)s",
|
|
51
|
+
"level": logging.INFO,
|
|
52
|
+
"stream": sys.stderr,
|
|
53
|
+
}
|
|
54
|
+
if options is not None:
|
|
55
|
+
settings |= options
|
|
56
|
+
logging.basicConfig(**settings)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def main():
|
|
60
|
+
"""Allocates Condor glide-in nodes a scheduler on a remote Node."""
|
|
61
|
+
|
|
62
|
+
p = AllocatorParser(sys.argv[0])
|
|
63
|
+
|
|
64
|
+
options = {}
|
|
65
|
+
if p.args.verbose:
|
|
66
|
+
options = {"level": logging.DEBUG}
|
|
67
|
+
setup_logging(options)
|
|
68
|
+
|
|
69
|
+
platform = p.getPlatform()
|
|
70
|
+
|
|
71
|
+
# load the CondorConfig file
|
|
72
|
+
execConfigName = find_package_file("execConfig.py", platform=platform)
|
|
73
|
+
configuration = CondorConfig()
|
|
74
|
+
configuration.loadFromStream(execConfigName.read())
|
|
75
|
+
|
|
76
|
+
# create the plugin class
|
|
77
|
+
schedulerName = configuration.platform.scheduler
|
|
78
|
+
schedulerClass = NamedClassFactory.createClass(
|
|
79
|
+
"lsst.ctrl.execute." + schedulerName + "Plugin"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# create the plugin
|
|
83
|
+
condor_info_file = find_package_file("condor-info.py", platform=platform)
|
|
84
|
+
scheduler: Allocator = schedulerClass(
|
|
85
|
+
platform, p.getArgs(), configuration, condor_info_file
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# submit the request
|
|
89
|
+
scheduler.submit()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == "__main__":
|
|
93
|
+
sys.exit(main())
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# LSST Data Management System
|
|
4
|
+
# Copyright 2008-2016 LSST Corporation.
|
|
5
|
+
#
|
|
6
|
+
# This product includes software developed by the
|
|
7
|
+
# LSST Project (http://www.lsst.org/).
|
|
8
|
+
#
|
|
9
|
+
# This program is free software: you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# This program is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the LSST License Statement and
|
|
20
|
+
# the GNU General Public License along with this program. If not,
|
|
21
|
+
# see <http://www.lsstcorp.org/LegalNotices/>.
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
import errno
|
|
25
|
+
import os
|
|
26
|
+
import re
|
|
27
|
+
import sys
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# extracts a line from a DAG file to show which ids were processed for a
|
|
31
|
+
# particular dag node
|
|
32
|
+
def main():
|
|
33
|
+
if len(sys.argv) != 3:
|
|
34
|
+
print("usage: %s dagNodeName filename" % os.path.basename(sys.argv[0]))
|
|
35
|
+
return errno.EINVAL
|
|
36
|
+
|
|
37
|
+
dagNode = sys.argv[1]
|
|
38
|
+
filename = sys.argv[2]
|
|
39
|
+
|
|
40
|
+
if not os.path.exists(filename):
|
|
41
|
+
print("file %s not found" % filename)
|
|
42
|
+
return errno.ENOENT
|
|
43
|
+
|
|
44
|
+
ex = r"VARS %s var1=\"(?P<idlist>.+?)\"" % dagNode
|
|
45
|
+
with open(filename) as file:
|
|
46
|
+
for line in file:
|
|
47
|
+
line = line.rstrip(" \n")
|
|
48
|
+
|
|
49
|
+
# look for the line with the dagnode name in it
|
|
50
|
+
# and extract everything after "var1", but not the quotes
|
|
51
|
+
values = re.search(ex, line)
|
|
52
|
+
if values is None:
|
|
53
|
+
continue
|
|
54
|
+
ids = values.groupdict()["idlist"]
|
|
55
|
+
print(ids)
|
|
56
|
+
break
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__":
|
|
60
|
+
sys.exit(main())
|