rda-python-common 1.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.

Potentially problematic release.


This version of rda-python-common might be problematic. Click here for more details.

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