rda-python-common 2.0.0__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.
- rda_python_common/PgCMD.py +603 -0
- rda_python_common/PgDBI.py +2306 -0
- rda_python_common/PgFile.py +3118 -0
- rda_python_common/PgLOG.py +1689 -0
- rda_python_common/PgLock.py +640 -0
- rda_python_common/PgOPT.py +1740 -0
- rda_python_common/PgSIG.py +1164 -0
- rda_python_common/PgSplit.py +299 -0
- rda_python_common/PgUtil.py +1854 -0
- rda_python_common/__init__.py +0 -0
- rda_python_common/pg_cmd.py +493 -0
- rda_python_common/pg_dbi.py +1885 -0
- rda_python_common/pg_file.py +2462 -0
- rda_python_common/pg_lock.py +533 -0
- rda_python_common/pg_log.py +1352 -0
- rda_python_common/pg_opt.py +1447 -0
- rda_python_common/pg_pass.py +92 -0
- rda_python_common/pg_sig.py +879 -0
- rda_python_common/pg_split.py +260 -0
- rda_python_common/pg_util.py +1534 -0
- rda_python_common/pgpassword.py +92 -0
- rda_python_common-2.0.0.dist-info/METADATA +20 -0
- rda_python_common-2.0.0.dist-info/RECORD +27 -0
- rda_python_common-2.0.0.dist-info/WHEEL +5 -0
- rda_python_common-2.0.0.dist-info/entry_points.txt +3 -0
- rda_python_common-2.0.0.dist-info/licenses/LICENSE +21 -0
- rda_python_common-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
#
|
|
2
|
+
###############################################################################
|
|
3
|
+
#
|
|
4
|
+
# Title : PgCMD.py
|
|
5
|
+
# Author : Zaihua Ji, zji@ucar.edu
|
|
6
|
+
# Date : 08/25/2020
|
|
7
|
+
# 2025-01-10 transferred to package rda_python_common from
|
|
8
|
+
# https://github.com/NCAR/rda-shared-libraries.git
|
|
9
|
+
# Purpose : python library module for functions to record commands for delayed
|
|
10
|
+
# mode or command recovery
|
|
11
|
+
#
|
|
12
|
+
# Github : https://github.com/NCAR/rda-python-common.git
|
|
13
|
+
#
|
|
14
|
+
###############################################################################
|
|
15
|
+
#
|
|
16
|
+
import os
|
|
17
|
+
import re
|
|
18
|
+
import sys
|
|
19
|
+
import time
|
|
20
|
+
from . import PgLOG
|
|
21
|
+
from . import PgSIG
|
|
22
|
+
from . import PgUtil
|
|
23
|
+
from . import PgLock
|
|
24
|
+
from . import PgDBI
|
|
25
|
+
|
|
26
|
+
# cached dscheck info
|
|
27
|
+
DSCHK = {}
|
|
28
|
+
BOPTIONS = {"hostname" : None, "qoptions" : None, "modules" : None, "environments" : None}
|
|
29
|
+
BFIELDS = ', '.join(BOPTIONS)
|
|
30
|
+
|
|
31
|
+
TRYLMTS = {
|
|
32
|
+
'dsquasar' : 3,
|
|
33
|
+
'dsarch' : 2,
|
|
34
|
+
'default' : 1
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
DLYPTN = r'(^|\s)-(d|BP|BatchProcess|DelayedMode)(\s|$)'
|
|
38
|
+
DLYOPT = {
|
|
39
|
+
'dsarch' : ' -d',
|
|
40
|
+
'dsupdt' : ' -d',
|
|
41
|
+
'dsrqst' : ' -d'
|
|
42
|
+
}
|
|
43
|
+
#
|
|
44
|
+
# params: dict array holding option values
|
|
45
|
+
# opt: 2 - each value of the dict array is a list; otherwise 1
|
|
46
|
+
# addhost: 1 to add host name too
|
|
47
|
+
# initial set Batch options passed in from command line
|
|
48
|
+
#
|
|
49
|
+
def set_batch_options(params, opt, addhost = 0):
|
|
50
|
+
|
|
51
|
+
if 'QS' in params: BOPTIONS['qoptions'] = (params['QS'][0] if opt == 2 else params['QS'])
|
|
52
|
+
if 'MO' in params: BOPTIONS['modules'] = (params['MO'][0] if opt == 2 else params['MO'])
|
|
53
|
+
if 'EV' in params: BOPTIONS['environments'] = (params['EV'][0] if opt == 2 else params['EV'])
|
|
54
|
+
if addhost and 'HN' in params: BOPTIONS['hostname'] = (params['HN'][0] if opt == 2 else params['HN'])
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# boptions: dict array holding batch options
|
|
58
|
+
# refresh: 1 to clean the previous cached global batch options
|
|
59
|
+
# checkkey: 1 to check and valid pre-defined fields
|
|
60
|
+
#
|
|
61
|
+
# fill Batch options recorded in RDADB
|
|
62
|
+
#
|
|
63
|
+
def fill_batch_options(boptions, refresh = 0, checkkey = 0):
|
|
64
|
+
|
|
65
|
+
if refresh:
|
|
66
|
+
for bkey in BOPTIONS:
|
|
67
|
+
BOPTIONS[bkey] = None # clean the hash before filling it up
|
|
68
|
+
|
|
69
|
+
if not boptions: return
|
|
70
|
+
for bkey in boptions:
|
|
71
|
+
if not checkkey or bkey in BOPTIONS:
|
|
72
|
+
BOPTIONS[bkey] = boptions[bkey]
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# bkey: batch option field name
|
|
76
|
+
# bval: batch option value
|
|
77
|
+
# override: 1 to override an existing option
|
|
78
|
+
#
|
|
79
|
+
# fill a single Batch option
|
|
80
|
+
#
|
|
81
|
+
def set_one_boption(bkey, bval, override = 0):
|
|
82
|
+
|
|
83
|
+
if bval:
|
|
84
|
+
if override or not ( bkey in BOPTIONS and BOPTIONS[bkey]): BOPTIONS[bkey] = bval
|
|
85
|
+
elif override and bkey in BOPTIONS and BOPTIONS[bkey]:
|
|
86
|
+
BOPTIONS[bkey] = None
|
|
87
|
+
|
|
88
|
+
#
|
|
89
|
+
# fill the passed in dict record with the pre-saved batch options
|
|
90
|
+
#
|
|
91
|
+
def get_batch_options(pgrec = None):
|
|
92
|
+
|
|
93
|
+
record = {}
|
|
94
|
+
for bkey in BOPTIONS:
|
|
95
|
+
if pgrec and bkey in pgrec and pgrec[bkey]:
|
|
96
|
+
record[bkey] = pgrec[bkey]
|
|
97
|
+
elif BOPTIONS[bkey]:
|
|
98
|
+
record[bkey] = BOPTIONS[bkey]
|
|
99
|
+
|
|
100
|
+
return record
|
|
101
|
+
|
|
102
|
+
#
|
|
103
|
+
# return delay mode option to append to argv string for a specified cmd
|
|
104
|
+
#
|
|
105
|
+
def append_delayed_mode(cmd, argv):
|
|
106
|
+
|
|
107
|
+
if cmd in DLYOPT and not re.search(DLYPTN, argv, re.I):
|
|
108
|
+
return DLYOPT[cmd]
|
|
109
|
+
else:
|
|
110
|
+
return ''
|
|
111
|
+
|
|
112
|
+
#
|
|
113
|
+
# check given doptions and cmd, and return the try limit and specified hosts
|
|
114
|
+
#
|
|
115
|
+
def get_delay_options(doptions, cmd):
|
|
116
|
+
|
|
117
|
+
mcount = 0
|
|
118
|
+
hosts = None
|
|
119
|
+
|
|
120
|
+
if doptions:
|
|
121
|
+
for bval in doptions:
|
|
122
|
+
if re.match(r'^(\d+)$', bval):
|
|
123
|
+
mcount = int(bval)
|
|
124
|
+
if mcount > 99: mcount = 99
|
|
125
|
+
else:
|
|
126
|
+
hosts = bval
|
|
127
|
+
|
|
128
|
+
if mcount == 0: mcount = get_try_limit(cmd)
|
|
129
|
+
if hosts: set_one_boption('hostname', hosts, 1)
|
|
130
|
+
|
|
131
|
+
return (mcount, hosts)
|
|
132
|
+
|
|
133
|
+
#
|
|
134
|
+
# find an existing dscheck record from the cached command argument; create and initialize one if not exist
|
|
135
|
+
#
|
|
136
|
+
def init_dscheck(oindex, otype, cmd, dsid, action, workdir = None, specialist = None, doptions = None, logact = 0):
|
|
137
|
+
|
|
138
|
+
cidx = 0
|
|
139
|
+
argv = PgLOG.argv_to_string(sys.argv[1:], 0, "Process in Delayed Mode")
|
|
140
|
+
argextra = None
|
|
141
|
+
|
|
142
|
+
if not logact: logact = PgLOG.LGEREX
|
|
143
|
+
if not workdir: workdir = os.getcwd()
|
|
144
|
+
if not specialist: specialist = PgLOG.PGLOG['CURUID']
|
|
145
|
+
|
|
146
|
+
(mcount, hosts) = get_delay_options(doptions, cmd)
|
|
147
|
+
|
|
148
|
+
if len(argv) > 100:
|
|
149
|
+
argextra = argv[100:]
|
|
150
|
+
argv = argv[0:100]
|
|
151
|
+
|
|
152
|
+
bck = PgLOG.PGLOG['BCKGRND']
|
|
153
|
+
PgLOG.PGLOG['BCKGRND'] = 0
|
|
154
|
+
cinfo = "{}-{}-Chk".format(PgLOG.PGLOG['HOSTNAME'], PgLOG.current_datetime())
|
|
155
|
+
pgrec = get_dscheck(cmd, argv, workdir, specialist, argextra, logact)
|
|
156
|
+
if pgrec: # found existing dscheck record
|
|
157
|
+
cidx = pgrec['cindex']
|
|
158
|
+
cmsg = "{}{}: {} batch process ".format(cinfo, cidx, get_command_info(pgrec))
|
|
159
|
+
cidx = PgLock.lock_dscheck(cidx, 1, PgLOG.LOGWRN)
|
|
160
|
+
if cidx < 0:
|
|
161
|
+
PgLOG.pglog(cmsg + "is Running, No restart", PgLOG.LOGWRN)
|
|
162
|
+
sys.exit(0)
|
|
163
|
+
if cidx > 0:
|
|
164
|
+
if not hosts and pgrec['hostname']:
|
|
165
|
+
hosts = pgrec['hostname']
|
|
166
|
+
set_one_boption('hostname', hosts, 0)
|
|
167
|
+
if mcount: pgrec['mcount'] = mcount
|
|
168
|
+
DSCHK['chkcnd'] = "cindex = {}".format(cidx)
|
|
169
|
+
if(pgrec['status'] == 'D' or pgrec['fcount'] and pgrec['dcount'] >= pgrec['fcount'] or
|
|
170
|
+
pgrec['tcount'] > pgrec['mcount'] or not pgrec['pid'] and pgrec['tcount'] == pgrec['mcount']):
|
|
171
|
+
PgLOG.pglog("{}is {}".format(cmsg, ('Done' if pgrec['status'] == 'D' else 'Finished')), PgLOG.LOGWRN)
|
|
172
|
+
PgLock.lock_dscheck(cidx, 0, logact)
|
|
173
|
+
sys.exit(0)
|
|
174
|
+
|
|
175
|
+
if not cidx: # add new dscheck record
|
|
176
|
+
record = {}
|
|
177
|
+
if hosts and re.match(r'^(ds\d|\d)\d\d.\d$', hosts):
|
|
178
|
+
PgLOG.pglog(hosts + ": Cannot pass DSID for hostname to submit batch process", PgLOG.LGEREX)
|
|
179
|
+
if oindex: set_command_control(oindex, otype, cmd, logact)
|
|
180
|
+
record['oindex'] = oindex
|
|
181
|
+
record['dsid'] = dsid
|
|
182
|
+
record['action'] = action
|
|
183
|
+
record['otype'] = otype
|
|
184
|
+
(record['date'], record['time']) = PgUtil.get_date_time()
|
|
185
|
+
record['command'] = cmd
|
|
186
|
+
record['argv'] = argv
|
|
187
|
+
if mcount > 0: record['mcount'] = mcount
|
|
188
|
+
record['specialist'] = specialist
|
|
189
|
+
record['workdir'] = workdir
|
|
190
|
+
if argextra: record['argextra'] = argextra
|
|
191
|
+
record.update(get_batch_options())
|
|
192
|
+
cidx = PgDBI.pgadd("dscheck", record, logact|PgLOG.AUTOID)
|
|
193
|
+
if cidx:
|
|
194
|
+
cmsg = "{}{}: {} Adds a new check".format(cinfo, cidx, get_command_info(record))
|
|
195
|
+
PgLOG.pglog(cmsg, PgLOG.LOGWRN)
|
|
196
|
+
sys.exit(0)
|
|
197
|
+
|
|
198
|
+
(chost, cpid) = PgLOG.current_process_info()
|
|
199
|
+
(rhost, rpid) = PgLOG.current_process_info(1)
|
|
200
|
+
|
|
201
|
+
if not check_command_specialist_host(hosts, chost, specialist, cmd, action, PgLOG.LOGERR):
|
|
202
|
+
PgLock.lock_dscheck(cidx, 0, logact)
|
|
203
|
+
sys.exit(1)
|
|
204
|
+
|
|
205
|
+
record = {}
|
|
206
|
+
record['status'] = "R"
|
|
207
|
+
if mcount > 0: record['mcount'] = mcount
|
|
208
|
+
record['bid'] = (cpid if PgLOG.PGLOG['CURBID'] else 0)
|
|
209
|
+
if pgrec['stttime'] and pgrec['chktime'] > pgrec['stttime']:
|
|
210
|
+
(record['ttltime'], record['quetime']) = get_dscheck_runtime(pgrec)
|
|
211
|
+
record['chktime'] = record['stttime'] = int(time.time())
|
|
212
|
+
if not pgrec['subtime']: record['subtime'] = record['stttime']
|
|
213
|
+
if dsid and not pgrec['dsid']: record['dsid'] = dsid
|
|
214
|
+
if action and not pgrec['action']: record['action'] = action
|
|
215
|
+
if oindex and not pgrec['oindex']: record['oindex'] = oindex
|
|
216
|
+
if otype and not pgrec['otype']: record['otype'] = otype
|
|
217
|
+
if argv and not pgrec['argv']: record['argv'] = argv
|
|
218
|
+
record['runhost'] = rhost
|
|
219
|
+
if pgrec['command'] == "dsrqst" and pgrec['oindex']:
|
|
220
|
+
(record['fcount'], record['dcount'], record['size']) = get_dsrqst_counts(pgrec, logact)
|
|
221
|
+
PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
|
|
222
|
+
|
|
223
|
+
DSCHK['dcount'] = pgrec['dcount']
|
|
224
|
+
DSCHK['fcount'] = pgrec['fcount']
|
|
225
|
+
DSCHK['size'] = pgrec['size']
|
|
226
|
+
DSCHK['cindex'] = cidx
|
|
227
|
+
DSCHK['dflags'] = pgrec['dflags']
|
|
228
|
+
PgLOG.PGLOG['DSCHECK'] = DSCHK # add global access link
|
|
229
|
+
if not PgLOG.PGLOG['BCKGRND']: PgLOG.PGLOG['BCKGRND'] = 1 # turn off screen output if not yet
|
|
230
|
+
tcnt = pgrec['tcount']
|
|
231
|
+
if not pgrec['pid']: tcnt += 1
|
|
232
|
+
tstr = "the {} run".format(PgLOG.int2order(tcnt)) if tcnt > 1 else "running"
|
|
233
|
+
pstr = "{}<{}>".format(chost, cpid)
|
|
234
|
+
if rhost != chost: pstr += "/{}<{}>".format(rhost, rpid)
|
|
235
|
+
PgLOG.pglog("{}Starts {} ({})".format(cmsg, tstr, pstr), PgLOG.LOGWRN)
|
|
236
|
+
PgLOG.PGLOG['BCKGRND'] = bck
|
|
237
|
+
|
|
238
|
+
return cidx
|
|
239
|
+
|
|
240
|
+
#
|
|
241
|
+
# check and validate if the current host is configured for the specialist
|
|
242
|
+
#
|
|
243
|
+
def check_command_specialist_host(hosts, chost, specialist, cmd, act = 0, logact = 0):
|
|
244
|
+
|
|
245
|
+
if cmd == 'dsrqst' and act == 'PR':
|
|
246
|
+
mflag = 'G'
|
|
247
|
+
else:
|
|
248
|
+
cnd = "command = '{}' AND specialist = '{}' AND hostname = '{}'".format(cmd, specialist, chost)
|
|
249
|
+
pgrec = PgDBI.pgget("dsdaemon", 'matchhost', cnd, logact)
|
|
250
|
+
mflag = (pgrec['matchhost'] if pgrec else 'G')
|
|
251
|
+
|
|
252
|
+
return PgLOG.check_process_host(hosts, chost, mflag, "{}-{}".format(specialist, cmd), logact)
|
|
253
|
+
|
|
254
|
+
#
|
|
255
|
+
# set command control info
|
|
256
|
+
#
|
|
257
|
+
def set_command_control(oindex, otype, cmd, logact = 0):
|
|
258
|
+
|
|
259
|
+
if not oindex: return
|
|
260
|
+
|
|
261
|
+
pgctl = None
|
|
262
|
+
if cmd == "dsrqst":
|
|
263
|
+
if otype == 'P':
|
|
264
|
+
pgrec = PgDBI.pgget("ptrqst", "rindex", "pindex = {}".format(oindex), logact)
|
|
265
|
+
if pgrec: pgctl = get_partition_control(pgrec, None, None, logact)
|
|
266
|
+
else:
|
|
267
|
+
pgrec = PgDBI.pgget("dsrqst", "dsid, gindex, cindex, rqsttype", "rindex = {}".format(oindex), logact)
|
|
268
|
+
if pgrec: pgctl = get_dsrqst_control(pgrec, logact)
|
|
269
|
+
elif cmd == "dsupdt":
|
|
270
|
+
if otype == 'L':
|
|
271
|
+
pgrec = PgDBI.pgget("dlupdt", "cindex", "lindex = {}".format(oindex), logact)
|
|
272
|
+
if not (pgrec and pgrec['cindex']): return
|
|
273
|
+
oindex = pgrec['cindex']
|
|
274
|
+
pgctl = PgDBI.pgget("dcupdt", BFIELDS, "cindex = {}".format(oindex), logact)
|
|
275
|
+
if pgctl:
|
|
276
|
+
for bkey in pgctl:
|
|
277
|
+
set_one_boption(bkey, pgctl[bkey], 0)
|
|
278
|
+
|
|
279
|
+
#
|
|
280
|
+
# get dsrqst control info
|
|
281
|
+
#
|
|
282
|
+
def get_dsrqst_control(pgrqst, logact = 0):
|
|
283
|
+
|
|
284
|
+
cflds = BFIELDS
|
|
285
|
+
if 'ptcount' in pgrqst and pgrqst['ptcount'] == 0: cflds += ", ptlimit, ptsize"
|
|
286
|
+
if pgrqst['cindex']:
|
|
287
|
+
pgctl = PgDBI.pgget("rcrqst", cflds, "cindex = {}".format(pgrqst['cindex']), logact)
|
|
288
|
+
else:
|
|
289
|
+
pgctl = None
|
|
290
|
+
if not pgctl:
|
|
291
|
+
gcnd = "dsid = '{}' AND gindex = ".format(pgrqst['dsid'])
|
|
292
|
+
if pgrqst['rqsttype'] in "ST":
|
|
293
|
+
tcnd = " AND (rqsttype = 'T' OR rqsttype = 'S')"
|
|
294
|
+
else:
|
|
295
|
+
tcnd = " AND rqsttype = '{}'".format(pgrqst['rqsttype'])
|
|
296
|
+
gindex = pgrqst['gindex']
|
|
297
|
+
while True:
|
|
298
|
+
pgctl = PgDBI.pgget("rcrqst", cflds, "{}{}{}".format(gcnd, gindex, tcnd), logact)
|
|
299
|
+
if pgctl or not gindex: break
|
|
300
|
+
pgctl = PgDBI.pgget("dsgroup", "pindex", "{}{}".format(gcnd, gindex), logact)
|
|
301
|
+
if not pgctl: break
|
|
302
|
+
gindex = pgctl['pindex']
|
|
303
|
+
|
|
304
|
+
return pgctl
|
|
305
|
+
|
|
306
|
+
#
|
|
307
|
+
# get dsrqst partition control info
|
|
308
|
+
#
|
|
309
|
+
def get_partition_control(pgpart, pgrqst = None, pgctl = None, logact = 0):
|
|
310
|
+
|
|
311
|
+
if not pgctl:
|
|
312
|
+
if not pgrqst and pgpart['rindex']:
|
|
313
|
+
pgrqst = PgDBI.pgget("dsrqst", "dsid, gindex, cindex, rqsttype", "rindex = {}".format(pgpart['rindex']), logact)
|
|
314
|
+
if pgrqst: pgctl = get_dsrqst_control(pgrqst, logact)
|
|
315
|
+
|
|
316
|
+
return pgctl
|
|
317
|
+
|
|
318
|
+
#
|
|
319
|
+
# build the dynamic options
|
|
320
|
+
#
|
|
321
|
+
def get_dynamic_options(cmd, oindex, otype):
|
|
322
|
+
|
|
323
|
+
if oindex: cmd += " {}".format(oindex)
|
|
324
|
+
if otype: cmd += ' ' + otype
|
|
325
|
+
ret = options = ''
|
|
326
|
+
for loop in range(3):
|
|
327
|
+
ret = PgLOG.pgsystem(cmd, PgLOG.LOGWRN, 279) # 1+2+4+16+256
|
|
328
|
+
if loop < 2 and PgLOG.PGLOG['SYSERR'] and 'Connection timed out' in PgLOG.PGLOG['SYSERR']:
|
|
329
|
+
time.sleep(PgSIG.PGSIG['ETIME'])
|
|
330
|
+
else:
|
|
331
|
+
break
|
|
332
|
+
if ret:
|
|
333
|
+
ret = ret.strip()
|
|
334
|
+
ms = re.match(r'^(-.+)/(-.+)$', ret)
|
|
335
|
+
if ms:
|
|
336
|
+
options = ms.group(1) if otype == 'R' else ms.group(2)
|
|
337
|
+
elif re.match(r'^(-.+)$', ret):
|
|
338
|
+
options = ret
|
|
339
|
+
if not options:
|
|
340
|
+
if ret: PgLOG.PGLOG['SYSERR'] += ret
|
|
341
|
+
PgLOG.PGLOG['SYSERR'] += " for {}".format(cmd)
|
|
342
|
+
|
|
343
|
+
return options
|
|
344
|
+
|
|
345
|
+
#
|
|
346
|
+
# retrieve a dscheck record for provided cmd, argv and other conditions
|
|
347
|
+
#
|
|
348
|
+
def get_dscheck(cmd, argv, workdir, specialist, argextra = None, logact = 0):
|
|
349
|
+
|
|
350
|
+
cnd = "command = '{}' AND specialist = '{}' AND argv = '{}'".format(cmd, specialist, argv)
|
|
351
|
+
pgrecs = PgDBI.pgmget("dscheck", "*", cnd, logact)
|
|
352
|
+
cnt = len(pgrecs['cindex']) if pgrecs else 0
|
|
353
|
+
if cnt == 0 and cmd in DLYOPT:
|
|
354
|
+
ms = re.match(r'^(.+){}$'.format(DLYOPT[cmd]), argv)
|
|
355
|
+
if ms:
|
|
356
|
+
argv = ms.group(1)
|
|
357
|
+
cnt = 1
|
|
358
|
+
elif not argextra:
|
|
359
|
+
dopt = append_delayed_mode(cmd, argv)
|
|
360
|
+
if dopt:
|
|
361
|
+
argv += dopt
|
|
362
|
+
cnt = 1
|
|
363
|
+
if cnt:
|
|
364
|
+
cnd = "command = '{}' AND specialist = '{}' AND argv = '{}'".format(cmd, specialist, argv)
|
|
365
|
+
pgrecs = PgDBI.pgmget("dscheck", "*", cnd, logact)
|
|
366
|
+
cnt = len(pgrecs['cindex']) if pgrecs else 0
|
|
367
|
+
|
|
368
|
+
for i in range(cnt):
|
|
369
|
+
pgrec = PgUtil.onerecord(pgrecs, i)
|
|
370
|
+
if pgrec['workdir'] and PgUtil.pgcmp(workdir, pgrec['workdir']): continue
|
|
371
|
+
if PgUtil.pgcmp(argextra, pgrec['argextra']): continue
|
|
372
|
+
return pgrec
|
|
373
|
+
|
|
374
|
+
return None
|
|
375
|
+
|
|
376
|
+
#
|
|
377
|
+
# delete one dsceck record fo given cindex
|
|
378
|
+
#
|
|
379
|
+
def delete_dscheck(pgrec, chkcnd, logact = 0):
|
|
380
|
+
|
|
381
|
+
if not chkcnd:
|
|
382
|
+
if pgrec:
|
|
383
|
+
chkcnd = "cindex = {}".format(pgrec['cindex'])
|
|
384
|
+
elif 'chkcnd' in DSCHK:
|
|
385
|
+
chkcnd = DSCHK['chkcnd']
|
|
386
|
+
else:
|
|
387
|
+
return 0 # nothing to delete
|
|
388
|
+
if not pgrec:
|
|
389
|
+
pgrec = PgDBI.pgget("dscheck", "*", chkcnd, logact)
|
|
390
|
+
if not pgrec: return 0 # dscheck record is gone
|
|
391
|
+
|
|
392
|
+
record = {}
|
|
393
|
+
record['cindex'] = pgrec['cindex']
|
|
394
|
+
record['command'] = pgrec['command']
|
|
395
|
+
record['dsid'] = (pgrec['dsid'] if pgrec['dsid'] else PgLOG.PGLOG['DEFDSID'])
|
|
396
|
+
record['action'] = (pgrec['action'] if pgrec['action'] else "UN")
|
|
397
|
+
record['specialist'] = pgrec['specialist']
|
|
398
|
+
record['hostname'] = pgrec['runhost']
|
|
399
|
+
if pgrec['bid']: record['bid'] = pgrec['bid']
|
|
400
|
+
if pgrec['command'] == "dsrqst" and pgrec['oindex']:
|
|
401
|
+
(record['fcount'], record['dcount'], record['size']) = get_dsrqst_counts(pgrec, logact)
|
|
402
|
+
else:
|
|
403
|
+
record['fcount'] = pgrec['fcount']
|
|
404
|
+
record['dcount'] = pgrec['dcount']
|
|
405
|
+
record['size'] = pgrec['size']
|
|
406
|
+
record['tcount'] = pgrec['tcount']
|
|
407
|
+
record['date'] = pgrec['date']
|
|
408
|
+
record['time'] = pgrec['time']
|
|
409
|
+
record['closetime'] = PgUtil.curtime(1)
|
|
410
|
+
(record['ttltime'], record['quetime']) = get_dscheck_runtime(pgrec)
|
|
411
|
+
record['argv'] = pgrec['argv']
|
|
412
|
+
if pgrec['argextra']:
|
|
413
|
+
record['argv'] += pgrec['argextra']
|
|
414
|
+
if len(record['argv']) > 255: record['argv'] = record['argv'][0:255]
|
|
415
|
+
if pgrec['errmsg']: record['errmsg'] = pgrec['errmsg']
|
|
416
|
+
record['status'] = ('F' if pgrec['status'] == "R" else pgrec['status'])
|
|
417
|
+
|
|
418
|
+
if PgDBI.pgget("dschkhist", "", chkcnd):
|
|
419
|
+
stat = PgDBI.pgupdt("dschkhist", record, chkcnd, logact)
|
|
420
|
+
else:
|
|
421
|
+
stat = PgDBI.pgadd("dschkhist", record, logact)
|
|
422
|
+
if stat:
|
|
423
|
+
cmsg = "{} cleaned as '{}' at {} on {}".format(get_command_info(pgrec), record['status'], PgLOG.current_datetime(), PgLOG.PGLOG['HOSTNAME'])
|
|
424
|
+
PgLOG.pglog("Chk{}: {}".format(pgrec['cindex'], cmsg), PgLOG.LOGWRN|PgLOG.FRCLOG)
|
|
425
|
+
stat = PgDBI.pgdel("dscheck", chkcnd, logact)
|
|
426
|
+
if record['status'] == "E" and 'errmsg' in record:
|
|
427
|
+
PgLOG.pglog("Chk{}: {} Exits with Error\n{}".format(pgrec['cindex'], get_command_info(pgrec), record['errmsg']), logact)
|
|
428
|
+
|
|
429
|
+
return stat
|
|
430
|
+
|
|
431
|
+
#
|
|
432
|
+
# get dsrqst fcount and dcount
|
|
433
|
+
#
|
|
434
|
+
def get_dsrqst_counts(pgchk, logact = 0):
|
|
435
|
+
|
|
436
|
+
fcount = pgchk['fcount']
|
|
437
|
+
dcount = pgchk['dcount']
|
|
438
|
+
size = pgchk['size']
|
|
439
|
+
|
|
440
|
+
if pgchk['otype'] == 'P':
|
|
441
|
+
table = 'ptrqst'
|
|
442
|
+
cnd = "pindex = {}".format(pgchk['oindex'])
|
|
443
|
+
fields = "fcount"
|
|
444
|
+
else:
|
|
445
|
+
table = 'dsrqst'
|
|
446
|
+
cnd = "rindex = {}".format(pgchk['oindex'])
|
|
447
|
+
fields = "fcount, pcount, size_input, size_request"
|
|
448
|
+
pgrec = PgDBI.pgget(table, fields, cnd, logact)
|
|
449
|
+
if pgrec:
|
|
450
|
+
fcnt = pgrec['fcount']
|
|
451
|
+
else:
|
|
452
|
+
fcnt = 0
|
|
453
|
+
pgrec = {'fcount' : 0}
|
|
454
|
+
if not fcnt: fcnt = PgDBI.pgget("wfrqst", "", cnd, logact)
|
|
455
|
+
if fcnt and fcount != fcnt: fcount = fcnt
|
|
456
|
+
if fcount:
|
|
457
|
+
if 'pcount' in pgrec and pgrec['pcount']:
|
|
458
|
+
dcnt = pgrec['pcount']
|
|
459
|
+
else:
|
|
460
|
+
dcnt = PgDBI.pgget("wfrqst", "", cnd + " AND status = 'O'", logact)
|
|
461
|
+
if dcnt and dcnt != dcount: dcount = dcnt
|
|
462
|
+
if not size:
|
|
463
|
+
if 'size_input' in pgrec and pgrec['size_input']:
|
|
464
|
+
if size != pgrec['size_input']: size = pgrec['size_input']
|
|
465
|
+
elif 'size_request' in pgrec and pgrec['size_request']:
|
|
466
|
+
if size != pgrec['size_request']: size = pgrec['size_request']
|
|
467
|
+
elif fcnt: # evaluate total size only if file count is set in request/partition record
|
|
468
|
+
pgrec = PgDBI.pgget("wfrqst", "sum(size) data_size", cnd, logact)
|
|
469
|
+
if pgrec and pgrec['data_size']: size = pgrec['data_size']
|
|
470
|
+
|
|
471
|
+
return (fcount, dcount, size)
|
|
472
|
+
|
|
473
|
+
#
|
|
474
|
+
# set dscheck fcount
|
|
475
|
+
#
|
|
476
|
+
def set_dscheck_fcount(count, logact = 0):
|
|
477
|
+
|
|
478
|
+
record = {'fcount' : count, 'chktime' : int(time.time())}
|
|
479
|
+
PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
|
|
480
|
+
DSCHK['fcount'] = count
|
|
481
|
+
|
|
482
|
+
return DSCHK['dcount'] # return Done count
|
|
483
|
+
|
|
484
|
+
#
|
|
485
|
+
# set dscheck dcount
|
|
486
|
+
#
|
|
487
|
+
def set_dscheck_dcount(count, size, logact = 0):
|
|
488
|
+
|
|
489
|
+
record = {'dcount' : count, 'size' : size, 'chktime' : int(time.time())}
|
|
490
|
+
PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
|
|
491
|
+
DSCHK['dcount'] = count
|
|
492
|
+
DSCHK['size'] = size
|
|
493
|
+
|
|
494
|
+
return DSCHK['dcount'] # return Done count
|
|
495
|
+
|
|
496
|
+
#
|
|
497
|
+
# add dscheck dcount
|
|
498
|
+
#
|
|
499
|
+
def add_dscheck_dcount(count, size, logact = 0):
|
|
500
|
+
|
|
501
|
+
record = {}
|
|
502
|
+
if count:
|
|
503
|
+
DSCHK['dcount'] += count
|
|
504
|
+
record['dcount'] = DSCHK['dcount']
|
|
505
|
+
if size:
|
|
506
|
+
DSCHK['size'] += size
|
|
507
|
+
record['size'] = DSCHK['size']
|
|
508
|
+
record['chktime'] = int(time.time())
|
|
509
|
+
PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
|
|
510
|
+
|
|
511
|
+
return DSCHK['dcount'] # return Done count
|
|
512
|
+
|
|
513
|
+
#
|
|
514
|
+
# set dscheck source information
|
|
515
|
+
#
|
|
516
|
+
def set_dscheck_attribute(fname, value, logact = 0):
|
|
517
|
+
|
|
518
|
+
record = {}
|
|
519
|
+
if value: record[fname] = value
|
|
520
|
+
record['chktime'] = int(time.time())
|
|
521
|
+
PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
|
|
522
|
+
|
|
523
|
+
#
|
|
524
|
+
# update dscheck status
|
|
525
|
+
#
|
|
526
|
+
def record_dscheck_status(stat, logact = 0):
|
|
527
|
+
|
|
528
|
+
pgrec = PgDBI.pgget("dscheck", "lockhost, pid", DSCHK['chkcnd'], logact)
|
|
529
|
+
if not pgrec: return 0
|
|
530
|
+
if not (pgrec['pid'] and pgrec['lockhost']): return 0
|
|
531
|
+
(chost, cpid) = PgLOG.current_process_info()
|
|
532
|
+
if pgrec['pid'] != cpid or pgrec['lockhost'] != chost: return 0
|
|
533
|
+
|
|
534
|
+
# update dscheck status only if it is still locked by the current process
|
|
535
|
+
record = {'status' : stat, 'chktime' : int(time.time()), 'pid' : 0}
|
|
536
|
+
return PgDBI.pgupdt("dscheck", record, DSCHK['chkcnd'], logact)
|
|
537
|
+
|
|
538
|
+
#
|
|
539
|
+
# get the number of tries to execute for a given cmd under dscheck control
|
|
540
|
+
#
|
|
541
|
+
def get_try_limit(cmd):
|
|
542
|
+
|
|
543
|
+
return (TRYLMTS[cmd] if cmd in TRYLMTS else TRYLMTS['default'])
|
|
544
|
+
|
|
545
|
+
#
|
|
546
|
+
# get the execution time for a dscheck command
|
|
547
|
+
#
|
|
548
|
+
def get_dscheck_runtime(pgrec, current = 0):
|
|
549
|
+
|
|
550
|
+
ttime = (0 if current else pgrec['ttltime'])
|
|
551
|
+
qtime = (0 if current else pgrec['quetime'])
|
|
552
|
+
|
|
553
|
+
# if pgrec['bid'] and PgLOG.PGLOG['CURBID']:
|
|
554
|
+
# if PgLOG.PGLOG['PGBATCH'] == PgLOG.PGLOG['SLMNAME']:
|
|
555
|
+
# stat = PgSIG.check_slurm_status(pgrec['bid'], PgLOG.LOGERR)
|
|
556
|
+
# if stat:
|
|
557
|
+
# if stat['PEND']: qtime += stat['PEND']
|
|
558
|
+
# if stat['TOTAL']: ttime += stat['TOTAL']
|
|
559
|
+
# return (ttime, qtime)
|
|
560
|
+
|
|
561
|
+
if pgrec['subtime']:
|
|
562
|
+
ttime += (pgrec['chktime'] - pgrec['subtime'])
|
|
563
|
+
if pgrec['stttime']: qtime += (pgrec['stttime'] - pgrec['subtime'])
|
|
564
|
+
|
|
565
|
+
return (ttime, qtime)
|
|
566
|
+
|
|
567
|
+
#
|
|
568
|
+
# retrieve a command string from a given dscheck record
|
|
569
|
+
#
|
|
570
|
+
def get_command_info(pgrec):
|
|
571
|
+
|
|
572
|
+
if pgrec['oindex']:
|
|
573
|
+
if pgrec['command'] == "dsupdt":
|
|
574
|
+
cinfo = "UC{}".format(pgrec['oindex'])
|
|
575
|
+
elif pgrec['command'] == "dsrqst":
|
|
576
|
+
if pgrec['otype'] == "P":
|
|
577
|
+
cinfo = "RPT{}".format(pgrec['oindex'])
|
|
578
|
+
else:
|
|
579
|
+
cinfo = "Rqst{}".format(pgrec['oindex'])
|
|
580
|
+
else:
|
|
581
|
+
cinfo ="{}-{}".format(pgrec['command'], pgrec['oindex'])
|
|
582
|
+
else:
|
|
583
|
+
cinfo =pgrec['command']
|
|
584
|
+
if pgrec['dsid']: cinfo += " " + pgrec['dsid']
|
|
585
|
+
if pgrec['action']: cinfo += " " + pgrec['action']
|
|
586
|
+
cinfo += " of " + pgrec['specialist']
|
|
587
|
+
|
|
588
|
+
return cinfo
|
|
589
|
+
|
|
590
|
+
#
|
|
591
|
+
# change the dscheck original command information
|
|
592
|
+
#
|
|
593
|
+
def change_dscheck_oinfo(oidx, otype, nidx, ntype):
|
|
594
|
+
|
|
595
|
+
cnd = "oindex = {} AND otype = '{}'".format(oidx, otype)
|
|
596
|
+
pgchk = PgDBI.pgget('dscheck', 'cindex, oindex, otype', cnd, PgLOG.LGEREX)
|
|
597
|
+
if not pgchk: return 0 # miss dscheck record to change
|
|
598
|
+
|
|
599
|
+
record = {}
|
|
600
|
+
DSCHK['oindex'] = record['oindex'] = nidx
|
|
601
|
+
DSCHK['otype'] = record['otype'] = ntype
|
|
602
|
+
cnd = "cindex = {}".format(pgchk['cindex'])
|
|
603
|
+
return PgDBI.pgupdt('dscheck', record, cnd, PgLOG.LGEREX)
|