rda-python-dscheck 2.0.8__py3-none-any.whl → 3.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_dscheck/PgCheck.py +6 -6
- rda_python_dscheck/ds_check.py +6 -6
- rda_python_dscheck/dscheck.py +6 -6
- rda_python_dscheck/dscheck.usg +65 -20
- rda_python_dscheck/pg_check.py +6 -6
- rda_python_dscheck-3.0.0.dist-info/METADATA +183 -0
- rda_python_dscheck-3.0.0.dist-info/RECORD +12 -0
- rda_python_dscheck-2.0.8.dist-info/METADATA +0 -93
- rda_python_dscheck-2.0.8.dist-info/RECORD +0 -12
- {rda_python_dscheck-2.0.8.dist-info → rda_python_dscheck-3.0.0.dist-info}/WHEEL +0 -0
- {rda_python_dscheck-2.0.8.dist-info → rda_python_dscheck-3.0.0.dist-info}/entry_points.txt +0 -0
- {rda_python_dscheck-2.0.8.dist-info → rda_python_dscheck-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {rda_python_dscheck-2.0.8.dist-info → rda_python_dscheck-3.0.0.dist-info}/top_level.txt +0 -0
rda_python_dscheck/PgCheck.py
CHANGED
|
@@ -211,7 +211,7 @@ def check_dscheck_options(cact, aname):
|
|
|
211
211
|
"Miss check index per Info option -CI(-CheckIndex)",
|
|
212
212
|
"Need Machine Hostname per -HN for new daemon control",
|
|
213
213
|
"Need Application command name per -CM for new daemon control",
|
|
214
|
-
"Must be {} to process Checks in daemon mode".format(PgLOG.PGLOG['
|
|
214
|
+
"Must be {} to process Checks in daemon mode".format(PgLOG.PGLOG['COMMONUSER']),
|
|
215
215
|
"Miss Command information per Info option -CM(-Command)",
|
|
216
216
|
]
|
|
217
217
|
erridx = -1
|
|
@@ -223,7 +223,7 @@ def check_dscheck_options(cact, aname):
|
|
|
223
223
|
if 'DM' in PgOPT.params:
|
|
224
224
|
if cact != "PC":
|
|
225
225
|
erridx = 0
|
|
226
|
-
elif PgLOG.PGLOG['CURUID'] != PgLOG.PGLOG['
|
|
226
|
+
elif PgLOG.PGLOG['CURUID'] != PgLOG.PGLOG['COMMONUSER']:
|
|
227
227
|
erridx = 5
|
|
228
228
|
elif 'CI' in PgOPT.params:
|
|
229
229
|
erridx = 1
|
|
@@ -280,7 +280,7 @@ def check_dscheck_options(cact, aname):
|
|
|
280
280
|
wtime = PgOPT.params['WI'] if 'WI' in PgOPT.params else 30
|
|
281
281
|
logon = PgOPT.params['LO'] if 'LO' in PgOPT.params else 1
|
|
282
282
|
PgSIG.start_none_daemon(aname, cact, PgOPT.params['LN'], 1, wtime, logon)
|
|
283
|
-
if not ('CI' in PgOPT.params or 'DS' in PgOPT.params or PgOPT.params['LN'] == PgLOG.PGLOG['
|
|
283
|
+
if not ('CI' in PgOPT.params or 'DS' in PgOPT.params or PgOPT.params['LN'] == PgLOG.PGLOG['COMMONUSER']):
|
|
284
284
|
PgOPT.set_default_value("SN", PgOPT.params['LN'])
|
|
285
285
|
|
|
286
286
|
# minimal wait interval in seconds for next check
|
|
@@ -581,7 +581,7 @@ def start_one_dscheck(pgrec, logact = 0):
|
|
|
581
581
|
|
|
582
582
|
lidx = get_process_host(limits, pgrec['hostname'], pgrec['command'], pgrec['action'], logact)
|
|
583
583
|
if lidx < 0 or skip_dscheck_record(pgrec, host, logact): return 0
|
|
584
|
-
cmd = "pgstart_{} ".format(specialist) if PgLOG.PGLOG['CURUID'] == PgLOG.PGLOG['
|
|
584
|
+
cmd = "pgstart_{} ".format(specialist) if PgLOG.PGLOG['CURUID'] == PgLOG.PGLOG['COMMONUSER'] else ""
|
|
585
585
|
if not PgUtil.pgcmp(host, PgLOG.PGLOG['PBSNAME'], 1):
|
|
586
586
|
if reach_dataset_limit(pgrec): return 0
|
|
587
587
|
cmd += get_specialist_shell(specialist) + 'qsub '
|
|
@@ -1532,7 +1532,7 @@ def validate_daemons():
|
|
|
1532
1532
|
if not pgrec:
|
|
1533
1533
|
PgOPT.action_error("Daemon Control Index '{}' is not in RDADB".format(val))
|
|
1534
1534
|
elif(PgOPT.OPTS[PgOPT.PGOPT['CACT']][2] > 0 and PgOPT.params['LN'] != pgrec['specialist'] and
|
|
1535
|
-
PgLOG.PGLOG['CURUID'] != PgLOG.PGLOG['
|
|
1535
|
+
PgLOG.PGLOG['CURUID'] != PgLOG.PGLOG['COMMONUSER']):
|
|
1536
1536
|
PgOPT.action_error("{}: must be {}, owner of Daemon Control Index {}".format(PgOPT.params['LN'], pgrec['specialist'], val))
|
|
1537
1537
|
else: # found none-equal condition sign
|
|
1538
1538
|
pgrec = PgDBI.pgmget("dsdaemon", "DISTINCT dindex",
|
|
@@ -1573,7 +1573,7 @@ def validate_checks():
|
|
|
1573
1573
|
if not pgrec:
|
|
1574
1574
|
PgOPT.action_error("Check Index '{}' is not in RDADB".format(val))
|
|
1575
1575
|
elif(PgOPT.OPTS[PgOPT.PGOPT['CACT']][2] > 0 and PgOPT.params['LN'] != pgrec['specialist'] and
|
|
1576
|
-
PgLOG.PGLOG['CURUID'] != PgLOG.PGLOG['
|
|
1576
|
+
PgLOG.PGLOG['CURUID'] != PgLOG.PGLOG['COMMONUSER']):
|
|
1577
1577
|
PgOPT.action_error("{}: must be {}, owner of Check Index {}".format(PgOPT.params['LN'], pgrec['specialist'], val))
|
|
1578
1578
|
else: # found none-equal condition sign
|
|
1579
1579
|
pgrec = PgDBI.pgmget("dscheck", "cindex", PgDBI.get_field_condition("cindex", PgOPT.params['CI'], 0, 1), PgOPT.PGOPT['extlog'])
|
rda_python_dscheck/ds_check.py
CHANGED
|
@@ -279,7 +279,7 @@ def set_daemon_info():
|
|
|
279
279
|
if pgrec:
|
|
280
280
|
modcnt += PgDBI.pgupdt(tname, record, cnd, PgOPT.PGOPT['extlog'])
|
|
281
281
|
else:
|
|
282
|
-
if 'specialist' not in record and PgOPT.params['LN'] != PgLOG.PGLOG['
|
|
282
|
+
if 'specialist' not in record and PgOPT.params['LN'] != PgLOG.PGLOG['COMMONUSER']: record['specialist'] = PgOPT.params['LN']
|
|
283
283
|
didx = PgDBI.pgadd(tname, record, PgOPT.PGOPT['extlog']|PgLOG.AUTOID)
|
|
284
284
|
if didx:
|
|
285
285
|
PgLOG.pglog("Daemon Control Index {} added".format(didx), PgOPT.PGOPT['wrnlog'])
|
|
@@ -506,12 +506,12 @@ def process_dschecks():
|
|
|
506
506
|
|
|
507
507
|
logact = PgLOG.LOGERR
|
|
508
508
|
|
|
509
|
-
if PgLOG.PGLOG['CURUID'] == PgLOG.PGLOG['
|
|
509
|
+
if PgLOG.PGLOG['CURUID'] == PgLOG.PGLOG['COMMONUSER'] and (time.time()%(3*PgSIG.PGSIG['CTIME'])) < 60:
|
|
510
510
|
logact |= PgLOG.EMEROL
|
|
511
511
|
|
|
512
512
|
cnd = PgOPT.get_hash_condition("dscheck", "ST", None, 1)
|
|
513
513
|
if cnd: cnd += " AND "
|
|
514
|
-
if 'SN' not in PgOPT.params and PgOPT.params['LN'] != PgLOG.PGLOG['
|
|
514
|
+
if 'SN' not in PgOPT.params and PgOPT.params['LN'] != PgLOG.PGLOG['COMMONUSER']:
|
|
515
515
|
cnd += "specialist = '{}' AND ".format(PgOPT.params['LN'])
|
|
516
516
|
|
|
517
517
|
if 'WR' in PgOPT.params: PgCheck.start_dsrqsts(cnd, logact)
|
|
@@ -530,12 +530,12 @@ def process_dscheck_options():
|
|
|
530
530
|
|
|
531
531
|
logact = PgLOG.LOGERR
|
|
532
532
|
|
|
533
|
-
if PgLOG.PGLOG['CURUID'] == PgLOG.PGLOG['
|
|
533
|
+
if PgLOG.PGLOG['CURUID'] == PgLOG.PGLOG['COMMONUSER'] and (time.time()%(3*PgSIG.PGSIG['CTIME'])) < 60:
|
|
534
534
|
logact |= PgLOG.EMEROL
|
|
535
535
|
|
|
536
536
|
cnd = PgOPT.get_hash_condition("dscheck", "ST", None, 1)
|
|
537
537
|
if cnd: cnd += " AND "
|
|
538
|
-
if 'SN' not in PgOPT.params and PgOPT.params['LN'] != PgLOG.PGLOG['
|
|
538
|
+
if 'SN' not in PgOPT.params and PgOPT.params['LN'] != PgLOG.PGLOG['COMMONUSER']:
|
|
539
539
|
cnd += "specialist = '{}' AND ".format(PgOPT.params['LN'])
|
|
540
540
|
|
|
541
541
|
acnd = PgOPT.get_hash_condition("dscheck", None, "ST", 1)
|
|
@@ -654,7 +654,7 @@ def check_host_connection():
|
|
|
654
654
|
hostname = pgrecs['hostname'][i]
|
|
655
655
|
cmd = "ssh {} ps".format(hostname)
|
|
656
656
|
if specialist != PgLOG.PGLOG['CURUID']:
|
|
657
|
-
if PgLOG.PGLOG['CURUID'] != PgLOG.PGLOG['
|
|
657
|
+
if PgLOG.PGLOG['CURUID'] != PgLOG.PGLOG['COMMONUSER']:
|
|
658
658
|
PgLOG.pglog("{}: Cannot check connection to '{}' for {}".format(PgLOG.PGLOG['CURUID'], hostname, specialist), PgLOG.LOGERR)
|
|
659
659
|
continue
|
|
660
660
|
else:
|
rda_python_dscheck/dscheck.py
CHANGED
|
@@ -225,7 +225,7 @@ class DsCheck(PgCheck):
|
|
|
225
225
|
if pgrec:
|
|
226
226
|
modcnt += self.pgupdt(tname, record, cnd, self.PGOPT['extlog'])
|
|
227
227
|
else:
|
|
228
|
-
if 'specialist' not in record and self.params['LN'] != self.PGLOG['
|
|
228
|
+
if 'specialist' not in record and self.params['LN'] != self.PGLOG['COMMONUSER']: record['specialist'] = self.params['LN']
|
|
229
229
|
didx = self.pgadd(tname, record, self.PGOPT['extlog']|self.AUTOID)
|
|
230
230
|
if didx:
|
|
231
231
|
self.pglog("Daemon Control Index {} added".format(didx), self.PGOPT['wrnlog'])
|
|
@@ -411,11 +411,11 @@ class DsCheck(PgCheck):
|
|
|
411
411
|
# process the checks
|
|
412
412
|
def process_dschecks(self):
|
|
413
413
|
logact = self.LOGERR
|
|
414
|
-
if self.PGLOG['CURUID'] == self.PGLOG['
|
|
414
|
+
if self.PGLOG['CURUID'] == self.PGLOG['COMMONUSER'] and (time.time()%(3*self.PGSIG['CTIME'])) < 60:
|
|
415
415
|
logact |= self.EMEROL
|
|
416
416
|
cnd = self.get_hash_condition("dscheck", "ST", None, 1)
|
|
417
417
|
if cnd: cnd += " AND "
|
|
418
|
-
if 'SN' not in self.params and self.params['LN'] != self.PGLOG['
|
|
418
|
+
if 'SN' not in self.params and self.params['LN'] != self.PGLOG['COMMONUSER']:
|
|
419
419
|
cnd += "specialist = '{}' AND ".format(self.params['LN'])
|
|
420
420
|
if 'WR' in self.params: self.start_dsrqsts(cnd, logact)
|
|
421
421
|
if 'WU' in self.params: self.start_dsupdts(cnd, logact)
|
|
@@ -427,11 +427,11 @@ class DsCheck(PgCheck):
|
|
|
427
427
|
# process the checks
|
|
428
428
|
def process_dscheck_options(self):
|
|
429
429
|
logact = self.LOGERR
|
|
430
|
-
if self.PGLOG['CURUID'] == self.PGLOG['
|
|
430
|
+
if self.PGLOG['CURUID'] == self.PGLOG['COMMONUSER'] and (time.time()%(3*self.PGSIG['CTIME'])) < 60:
|
|
431
431
|
logact |= self.EMEROL
|
|
432
432
|
cnd = self.get_hash_condition("dscheck", "ST", None, 1)
|
|
433
433
|
if cnd: cnd += " AND "
|
|
434
|
-
if 'SN' not in self.params and self.params['LN'] != self.PGLOG['
|
|
434
|
+
if 'SN' not in self.params and self.params['LN'] != self.PGLOG['COMMONUSER']:
|
|
435
435
|
cnd += "specialist = '{}' AND ".format(self.params['LN'])
|
|
436
436
|
acnd = self.get_hash_condition("dscheck", None, "ST", 1)
|
|
437
437
|
if acnd: acnd += " AND "
|
|
@@ -513,7 +513,7 @@ class DsCheck(PgCheck):
|
|
|
513
513
|
hostname = pgrecs['hostname'][i]
|
|
514
514
|
cmd = "ssh {} ps".format(hostname)
|
|
515
515
|
if specialist != self.PGLOG['CURUID']:
|
|
516
|
-
if self.PGLOG['CURUID'] != self.PGLOG['
|
|
516
|
+
if self.PGLOG['CURUID'] != self.PGLOG['COMMONUSER']:
|
|
517
517
|
self.pglog("{}: Cannot check connection to '{}' for {}".format(self.PGLOG['CURUID'], hostname, specialist), self.LOGERR)
|
|
518
518
|
continue
|
|
519
519
|
else:
|
rda_python_dscheck/dscheck.usg
CHANGED
|
@@ -9,18 +9,30 @@ well as any specialist-defined command.
|
|
|
9
9
|
|
|
10
10
|
The mental model has three layers:
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
A check record - a row in GDEXDB that captures one deferred command:
|
|
13
|
+
its name, arguments, owner, working directory,
|
|
14
|
+
target host, retry policy, and current status.
|
|
15
|
+
daemon/crontab control - a row in GDEXDB that tells the centralized
|
|
16
|
+
'dscheck' driver (whether running as a long-lived
|
|
17
|
+
daemon or as a short-lived crontab invocation) how
|
|
18
|
+
many concurrent processes of a given command a
|
|
19
|
+
given specialist may run on a given host, and at
|
|
20
|
+
what host priority.
|
|
21
|
+
The dscheck driver - a process that wakes on a fixed interval, adds
|
|
22
|
+
due 'dsupdt'/'dsrqst' check records, and starts
|
|
23
|
+
(or restarts) commands from check records on
|
|
24
|
+
hosts chosen according to daemon control
|
|
25
|
+
configuration. The driver may run either as a
|
|
26
|
+
long-running daemon ('-PC -DM start') or as a
|
|
27
|
+
short-lived crontab invocation ('-PC' every
|
|
28
|
+
minute via cron). It may run as the specialist's
|
|
29
|
+
own loginname, or as PGLOG['COMMONUSER'] (default
|
|
30
|
+
'gdexdata'). When it runs as COMMONUSER it also
|
|
31
|
+
submits PBS jobs (via qsub) on behalf of every
|
|
32
|
+
specialist whose loginname belongs to the same
|
|
33
|
+
group as COMMONUSER and who has a properly
|
|
34
|
+
installed pgstart_<loginname> binary (see the
|
|
35
|
+
rda_python_setuid README, '-p|--pgstart').
|
|
24
36
|
|
|
25
37
|
Typical lifecycle of a deferred command:
|
|
26
38
|
|
|
@@ -101,20 +113,29 @@ are accepted, and aliases are noted with each option.
|
|
|
101
113
|
dscheck -h -AC
|
|
102
114
|
|
|
103
115
|
List your own daemon control records:
|
|
116
|
+
|
|
104
117
|
dscheck -GD
|
|
105
118
|
|
|
106
119
|
List your own active check records:
|
|
120
|
+
|
|
107
121
|
dscheck -GC
|
|
108
122
|
|
|
109
123
|
Add a deferred run of a script on PBS:
|
|
124
|
+
|
|
110
125
|
dscheck -AC -CM myscript.sh -HN PBS
|
|
111
126
|
|
|
112
127
|
Email yourself the status of all your active checks:
|
|
128
|
+
|
|
113
129
|
dscheck -EC
|
|
114
130
|
|
|
115
|
-
Start the dscheck daemon (typical for the operator):
|
|
131
|
+
Start the dscheck driver as a long-running daemon (typical for the operator):
|
|
132
|
+
|
|
116
133
|
dscheck -PC -DM start
|
|
117
134
|
|
|
135
|
+
Or run the dscheck driver from crontab every minute (lightweight alternative):
|
|
136
|
+
|
|
137
|
+
* * * * * dscheck -PC
|
|
138
|
+
|
|
118
139
|
2.2 Filters and Special Characters in Queries
|
|
119
140
|
|
|
120
141
|
For Get-style actions (-GD, -GC), Info options are interpreted as query
|
|
@@ -439,7 +460,13 @@ Unlock Check - clear leftover lock information after an abnormal exit.
|
|
|
439
460
|
|
|
440
461
|
3.3 Check Process Actions
|
|
441
462
|
|
|
442
|
-
The dscheck
|
|
463
|
+
The dscheck driver starts and restarts deferred commands automatically.
|
|
464
|
+
It can run either as a long-running daemon ('-PC -DM start'), or as a
|
|
465
|
+
short-lived crontab invocation ('-PC' run every minute by cron). The
|
|
466
|
+
driver may run as the specialist's own loginname, or as
|
|
467
|
+
PGLOG['COMMONUSER'] (default 'gdexdata'); when run as COMMONUSER it
|
|
468
|
+
also submits PBS jobs on behalf of every specialist in COMMONUSER's
|
|
469
|
+
group that has a properly installed pgstart_<loginname> binary.
|
|
443
470
|
Operators (and, in non-daemon mode, specialists) can also drive command
|
|
444
471
|
execution from the command line, interrupt running commands, and email
|
|
445
472
|
status summaries.
|
|
@@ -482,11 +509,28 @@ Available actions:
|
|
|
482
509
|
-DM stop, -DM logon, and -DM logoff stop the daemon, enable detailed
|
|
483
510
|
logging, and disable detailed logging respectively.
|
|
484
511
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
-
|
|
488
|
-
|
|
489
|
-
|
|
512
|
+
Crontab mode (cron-driven, no -DM):
|
|
513
|
+
The same -PC action can be driven from cron instead of running as a
|
|
514
|
+
long-lived daemon. A typical setup is to run it every minute:
|
|
515
|
+
* * * * * dscheck -PC
|
|
516
|
+
Each invocation performs one cycle (add due 'dsupdt'/'dsrqst' work,
|
|
517
|
+
then start/restart checks) and exits. -WI is ignored because the
|
|
518
|
+
cron schedule controls the cadence.
|
|
519
|
+
|
|
520
|
+
Non-daemon (one-shot) mode:
|
|
521
|
+
Without -DM and not driven by cron, dscheck processes the current
|
|
522
|
+
set of check records once. -WU and -WR must be set explicitly if you
|
|
523
|
+
want due 'dsupdt'/'dsrqst' work to be added before processing. -CI
|
|
524
|
+
restricts processing to specific check indices.
|
|
525
|
+
|
|
526
|
+
Running user (daemon or crontab mode):
|
|
527
|
+
The driver may run as the specialist's own loginname (handling only
|
|
528
|
+
that specialist's checks), or as PGLOG['COMMONUSER'] (default
|
|
529
|
+
'gdexdata'). When run as COMMONUSER, it also submits PBS jobs (via
|
|
530
|
+
qsub) on behalf of every specialist whose loginname is in the same
|
|
531
|
+
group as COMMONUSER and who has a properly installed
|
|
532
|
+
pgstart_<loginname> binary (see rda_python_setuid, option
|
|
533
|
+
'-p|--pgstart').
|
|
490
534
|
|
|
491
535
|
3.3.2 Interrupt Check
|
|
492
536
|
-IC or -InterruptCheck, stops a running command and recursively kills
|
|
@@ -653,7 +697,8 @@ multiple values is an error.
|
|
|
653
697
|
input files. Defaults to '<!>'.
|
|
654
698
|
|
|
655
699
|
-WI or -WaitInterval, the time the dscheck daemon sleeps between
|
|
656
|
-
cycles. Defaults to 120 seconds (2 minutes).
|
|
700
|
+
cycles. Defaults to 120 seconds (2 minutes). Ignored when -PC is
|
|
701
|
+
driven from cron, since the cron schedule controls the cadence.
|
|
657
702
|
|
|
658
703
|
5.2 Multi-Value Info Options
|
|
659
704
|
|
rda_python_dscheck/pg_check.py
CHANGED
|
@@ -190,7 +190,7 @@ class PgCheck(PgOPT, PgCMD):
|
|
|
190
190
|
"Miss check index per Info option -CI(-CheckIndex)",
|
|
191
191
|
"Need Machine Hostname per -HN for new daemon control",
|
|
192
192
|
"Need Application command name per -CM for new daemon control",
|
|
193
|
-
"Must be {} to process Checks in daemon mode".format(self.PGLOG['
|
|
193
|
+
"Must be {} to process Checks in daemon mode".format(self.PGLOG['COMMONUSER']),
|
|
194
194
|
"Miss Command information per Info option -CM(-Command)",
|
|
195
195
|
]
|
|
196
196
|
erridx = -1
|
|
@@ -200,7 +200,7 @@ class PgCheck(PgOPT, PgCMD):
|
|
|
200
200
|
if 'DM' in self.params:
|
|
201
201
|
if cact != "PC":
|
|
202
202
|
erridx = 0
|
|
203
|
-
elif self.PGLOG['CURUID'] != self.PGLOG['
|
|
203
|
+
elif self.PGLOG['CURUID'] != self.PGLOG['COMMONUSER']:
|
|
204
204
|
erridx = 5
|
|
205
205
|
elif 'CI' in self.params:
|
|
206
206
|
erridx = 1
|
|
@@ -254,7 +254,7 @@ class PgCheck(PgOPT, PgCMD):
|
|
|
254
254
|
wtime = self.params['WI'] if 'WI' in self.params else 30
|
|
255
255
|
logon = self.params['LO'] if 'LO' in self.params else 1
|
|
256
256
|
self.start_none_daemon(aname, cact, self.params['LN'], 1, wtime, logon)
|
|
257
|
-
if not ('CI' in self.params or 'DS' in self.params or self.params['LN'] == self.PGLOG['
|
|
257
|
+
if not ('CI' in self.params or 'DS' in self.params or self.params['LN'] == self.PGLOG['COMMONUSER']):
|
|
258
258
|
self.set_default_value("SN", self.params['LN'])
|
|
259
259
|
# minimal wait interval in seconds for next check
|
|
260
260
|
self.PGOPT['minlimit'] = self.params['WI'] = self.PGSIG['WTIME']
|
|
@@ -493,7 +493,7 @@ class PgCheck(PgOPT, PgCMD):
|
|
|
493
493
|
return 0
|
|
494
494
|
lidx = self.get_process_host(limits, pgrec['hostname'], pgrec['command'], pgrec['action'], logact)
|
|
495
495
|
if lidx < 0 or self.skip_dscheck_record(pgrec, host, logact): return 0
|
|
496
|
-
cmd = "pgstart_{} ".format(specialist) if self.PGLOG['CURUID'] == self.PGLOG['
|
|
496
|
+
cmd = "pgstart_{} ".format(specialist) if self.PGLOG['CURUID'] == self.PGLOG['COMMONUSER'] else ""
|
|
497
497
|
if not self.pgcmp(host, self.PGLOG['PBSNAME'], 1):
|
|
498
498
|
if self.reach_dataset_limit(pgrec): return 0
|
|
499
499
|
cmd += self.get_specialist_shell(specialist) + 'qsub '
|
|
@@ -1274,7 +1274,7 @@ class PgCheck(PgOPT, PgCMD):
|
|
|
1274
1274
|
if not pgrec:
|
|
1275
1275
|
self.action_error("Daemon Control Index '{}' is not in RDADB".format(val))
|
|
1276
1276
|
elif(self.OPTS[self.PGOPT['CACT']][2] > 0 and self.params['LN'] != pgrec['specialist'] and
|
|
1277
|
-
self.PGLOG['CURUID'] != self.PGLOG['
|
|
1277
|
+
self.PGLOG['CURUID'] != self.PGLOG['COMMONUSER']):
|
|
1278
1278
|
self.action_error("{}: must be {}, owner of Daemon Control Index {}".format(self.params['LN'], pgrec['specialist'], val))
|
|
1279
1279
|
else: # found none-equal condition sign
|
|
1280
1280
|
pgrec = self.pgmget("dsdaemon", "DISTINCT dindex",
|
|
@@ -1310,7 +1310,7 @@ class PgCheck(PgOPT, PgCMD):
|
|
|
1310
1310
|
if not pgrec:
|
|
1311
1311
|
self.action_error("Check Index '{}' is not in RDADB".format(val))
|
|
1312
1312
|
elif(self.OPTS[self.PGOPT['CACT']][2] > 0 and self.params['LN'] != pgrec['specialist'] and
|
|
1313
|
-
self.PGLOG['CURUID'] != self.PGLOG['
|
|
1313
|
+
self.PGLOG['CURUID'] != self.PGLOG['COMMONUSER']):
|
|
1314
1314
|
self.action_error("{}: must be {}, owner of Check Index {}".format(self.params['LN'], pgrec['specialist'], val))
|
|
1315
1315
|
else: # found none-equal condition sign
|
|
1316
1316
|
pgrec = self.pgmget("dscheck", "cindex", self.get_field_condition("cindex", self.params['CI'], 0, 1), self.PGOPT['extlog'])
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rda_python_dscheck
|
|
3
|
+
Version: 3.0.0
|
|
4
|
+
Summary: RDA python package to add and process batch jobs
|
|
5
|
+
Author-email: Zaihua Ji <zji@ucar.edu>
|
|
6
|
+
Project-URL: Homepage, https://github.com/NCAR/rda-python-dscheck
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: rda_python_common
|
|
15
|
+
Requires-Dist: rda_python_setuid
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# dscheck
|
|
19
|
+
|
|
20
|
+
Python project to add and process batch jobs for the
|
|
21
|
+
[NSF NCAR Geoscience Data Exchange (GDEX)](https://gdex.ucar.edu).
|
|
22
|
+
|
|
23
|
+
The user guide for this utility tool can be viewed at:
|
|
24
|
+
[User guide](https://gdex-docs-dscheck.readthedocs.io).
|
|
25
|
+
|
|
26
|
+
## Source layout
|
|
27
|
+
|
|
28
|
+
The package lives under `src/rda_python_dscheck/`. The three files most
|
|
29
|
+
relevant to setup and customization are:
|
|
30
|
+
|
|
31
|
+
- **`dscheck.py`** — entry point installed as the `dscheck` console script.
|
|
32
|
+
Defines the `DsCheck` class which subclasses `PgCheck`, parses command-line
|
|
33
|
+
options via `self.parsing_input`, and dispatches to the appropriate action
|
|
34
|
+
handler (`add_check_info`, `process_check`, `get_check_info`,
|
|
35
|
+
`set_dscheck_options`, ...). Build new actions by adding a method here and
|
|
36
|
+
routing to it from `start_actions()`.
|
|
37
|
+
|
|
38
|
+
- **`pg_check.py`** — defines the `PgCheck` class (inherits from `PgCMD` in
|
|
39
|
+
`rda_python_common`). Holds the master `OPTS` option table, the `ALIAS`
|
|
40
|
+
map for long/alias names, the `TBLHASH` table field maps for `dscheck` and
|
|
41
|
+
`dsdaemon`, and the helper methods shared by every action (option
|
|
42
|
+
validation, dynamic batch-option resolution, daemon control,
|
|
43
|
+
host/specialist resolution, etc.). Add or change options here, then
|
|
44
|
+
document them in `dscheck.usg`.
|
|
45
|
+
|
|
46
|
+
- **`dscheck.usg`** — single source of truth for the user-facing documentation
|
|
47
|
+
displayed by `dscheck -?` and rendered as the
|
|
48
|
+
[user guide](https://gdex-docs-dscheck.readthedocs.io). Section 3 lists
|
|
49
|
+
Action options, Section 4 lists Mode options, and Section 5 lists Single-
|
|
50
|
+
and Multi-Value Info options. When you add a new option to `OPTS` in
|
|
51
|
+
`pg_check.py`, add a matching entry to the appropriate subsection of this
|
|
52
|
+
file and (if relevant) to the per-action usage block in Section 3.
|
|
53
|
+
|
|
54
|
+
## Environment setup
|
|
55
|
+
|
|
56
|
+
Create a Python environment first; package installs in the next section run
|
|
57
|
+
inside whichever environment you activate here.
|
|
58
|
+
|
|
59
|
+
### Option A — Python venv (DECS machines)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
|
|
63
|
+
source $ENVHOME/bin/activate
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Option B — Conda (DAV/Casper)
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
conda create --prefix $ENVHOME python=3.12 # e.g. /glade/work/gdexdata/conda-envs/pg-gdex
|
|
70
|
+
conda activate $ENVHOME
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Dependencies
|
|
74
|
+
|
|
75
|
+
In addition to `rda_python_common`, this package depends on
|
|
76
|
+
`rda_python_setuid`. When `dscheck` runs as the common user, the
|
|
77
|
+
`start_one_dscheck()` method in `pg_check.py` submits each PBS batch job via a
|
|
78
|
+
`pgstart_<specialist>` wrapper, and those per-specialist `pgstart_*` wrappers
|
|
79
|
+
are provisioned by `rda_python_setuid`. Both dependencies are declared in
|
|
80
|
+
`pyproject.toml` and are pulled in automatically on install.
|
|
81
|
+
|
|
82
|
+
## Installing rda-python-dscheck
|
|
83
|
+
|
|
84
|
+
Pick whichever install mode fits your workflow. All variants pull in the
|
|
85
|
+
transitive dependencies (`rda_python_common` and `rda_python_setuid`)
|
|
86
|
+
automatically.
|
|
87
|
+
|
|
88
|
+
For local development, clone this repo alongside your project and install it
|
|
89
|
+
in editable mode so that changes are picked up without re-installing:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
git clone https://github.com/NCAR/rda-python-dscheck.git
|
|
93
|
+
cd rda-python-dscheck
|
|
94
|
+
pip install -e .
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
To test a specific branch (e.g. an in-progress feature or fix branch), pass
|
|
98
|
+
`-b/--branch` to `git clone`:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
git clone -b <branch-name> https://github.com/NCAR/rda-python-dscheck.git
|
|
102
|
+
cd rda-python-dscheck
|
|
103
|
+
pip install -e .
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For a regular (non-editable) install from a checkout:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install /path/to/rda-python-dscheck
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For a production install on a system that uses the published distribution:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pip install rda_python_dscheck
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
To upgrade an existing install to the latest published release:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pip install --upgrade rda_python_dscheck
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Setuid Setup
|
|
125
|
+
|
|
126
|
+
Unlike `dsarch`, `dscheck` is **not** wired as a `setuid_dscheck` link. It
|
|
127
|
+
relies instead on the `pgstart_*` setuid binaries provided by
|
|
128
|
+
`rda_python_setuid` (pulled in automatically as a dependency):
|
|
129
|
+
|
|
130
|
+
- In cron, `dscheck` itself is run as the common user `PGLOG['COMMONUSER']`
|
|
131
|
+
(default `gdexdata`) via `pgstart_<COMMONUSER> dscheck` (e.g.
|
|
132
|
+
`pgstart_gdexdata dscheck`).
|
|
133
|
+
- While running as the common user, `start_one_dscheck()` in `pg_check.py`
|
|
134
|
+
submits each PBS batch job as the owning specialist via
|
|
135
|
+
`pgstart_<specialist> ... qsub ...`, so each job runs under that specialist's
|
|
136
|
+
identity.
|
|
137
|
+
|
|
138
|
+
This means setup is about installing the `pgstart_*` binaries, not creating a
|
|
139
|
+
`dscheck -> pywrapper` symlink.
|
|
140
|
+
|
|
141
|
+
> **Note:** The setuid actions in this section are optional. If
|
|
142
|
+
> `rda_python_setuid` is already installed and fully set up in your
|
|
143
|
+
> environment, you can skip this section.
|
|
144
|
+
|
|
145
|
+
### Install the pgstart binaries (requires sudo access to each user)
|
|
146
|
+
|
|
147
|
+
Run these steps once per environment:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# 1. Compile the pywrapper C binary (once per environment):
|
|
151
|
+
pywrapper-install -c|--compile -n|--username gdexdata
|
|
152
|
+
|
|
153
|
+
# 2. Install pgstart_<COMMONUSER> so cron can run 'pgstart_gdexdata dscheck':
|
|
154
|
+
pywrapper-install -p|--pgstart -n|--username gdexdata
|
|
155
|
+
|
|
156
|
+
# 3. Install a pgstart_<specialist> binary for each specialist whose jobs
|
|
157
|
+
# dscheck submits. Run either by PGLOG['ADMINUSER'] (default zji, if it
|
|
158
|
+
# has 'sudo -u <specialist>'), or by <specialist> directly:
|
|
159
|
+
pywrapper-install -p|--pgstart -n|--username <specialist>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`pywrapper-install` with no arguments displays the full user guide.
|
|
163
|
+
|
|
164
|
+
### Update an existing installation (no sudo required)
|
|
165
|
+
|
|
166
|
+
When the package is upgraded and a new `pywrapper.c` is bundled, recompile and
|
|
167
|
+
reinstall all `pgstart_*` binaries using the existing ones:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
pywrapper-install -u|--update
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Documentation sync
|
|
174
|
+
|
|
175
|
+
The user guide rendered at
|
|
176
|
+
[gdex-docs-dscheck.readthedocs.io](https://gdex-docs-dscheck.readthedocs.io) is
|
|
177
|
+
generated from `src/rda_python_dscheck/dscheck.usg` in this repository. When a
|
|
178
|
+
pull request that modifies `dscheck.usg` is merged here, an automated workflow
|
|
179
|
+
converts the updated `dscheck.usg` into the RST-format source files in the
|
|
180
|
+
[gdex-docs-dscheck](https://github.com/NCAR/gdex-docs-dscheck) repository and
|
|
181
|
+
opens a pull request there with the regenerated docs, ready for review and
|
|
182
|
+
merge. No manual RST editing is required — keep all user-facing content in
|
|
183
|
+
`dscheck.usg` and let the sync produce the docs.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
rda_python_dscheck/PgCheck.py,sha256=c936Q7UwatjxjtVDXYrprs61gZW6-LncXMoKWSXf4RY,64229
|
|
2
|
+
rda_python_dscheck/__init__.py,sha256=4Wtgj9ephcxz20cPTI4SZ_XCuCM0oqtfq9wL8kcVr3Y,734
|
|
3
|
+
rda_python_dscheck/ds_check.py,sha256=9Zjoz12STauUmtucjLJHBzRoCZzqfLrsZk0FKYxTwcM,24315
|
|
4
|
+
rda_python_dscheck/dscheck.py,sha256=XxVtSQZLmfWCjeVPRQK7PCYCOPBdWOVu6InxfYGJadE,24817
|
|
5
|
+
rda_python_dscheck/dscheck.usg,sha256=IpbGbcCdhpNUgrMEKzRSWqX3n_vO6G8SUre3wYl4cQ4,34076
|
|
6
|
+
rda_python_dscheck/pg_check.py,sha256=ecxl1tt0KN72gxDa5mseV_sOiQ_jcclxdtSDF1X-QzE,67488
|
|
7
|
+
rda_python_dscheck-3.0.0.dist-info/licenses/LICENSE,sha256=1dck4EAQwv8QweDWCXDx-4Or0S8YwiCstaso_H57Pno,1097
|
|
8
|
+
rda_python_dscheck-3.0.0.dist-info/METADATA,sha256=itqH1vqBCI8YSnn0RbiUSYGAutFDqV14-D3OydzprvU,6798
|
|
9
|
+
rda_python_dscheck-3.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
10
|
+
rda_python_dscheck-3.0.0.dist-info/entry_points.txt,sha256=frVByX3Vp_Pd_zq93SXfItr5OMTd5tKeZzu5pbVXiGA,60
|
|
11
|
+
rda_python_dscheck-3.0.0.dist-info/top_level.txt,sha256=NrvWqcHMRlQZJb0w85JrDlSXTp9DF-pDRQaAEABzFts,19
|
|
12
|
+
rda_python_dscheck-3.0.0.dist-info/RECORD,,
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: rda_python_dscheck
|
|
3
|
-
Version: 2.0.8
|
|
4
|
-
Summary: RDA python package to add and process batch jobs
|
|
5
|
-
Author-email: Zaihua Ji <zji@ucar.edu>
|
|
6
|
-
Project-URL: Homepage, https://github.com/NCAR/rda-python-dscheck
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
-
Classifier: Operating System :: OS Independent
|
|
10
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
-
Requires-Python: >=3.7
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
Requires-Dist: rda_python_common
|
|
15
|
-
Dynamic: license-file
|
|
16
|
-
|
|
17
|
-
# dscheck
|
|
18
|
-
|
|
19
|
-
Python project to add and process batch jobs for the [NSF NCAR Geoscience Data Exchange (GDEX)](https://gdex.ucar.edu).
|
|
20
|
-
|
|
21
|
-
The user guide for this utility tool can be viewed at: [User guide](https://gdex-docs-dscheck.readthedocs.io).
|
|
22
|
-
|
|
23
|
-
## Source layout
|
|
24
|
-
|
|
25
|
-
The package lives under `src/rda_python_dscheck/`. The three files most
|
|
26
|
-
relevant to setup and customization are:
|
|
27
|
-
|
|
28
|
-
- **`dscheck.py`** — entry point installed as the `setuid_dscheck`
|
|
29
|
-
console script. Defines the `DsCheck` class which subclasses
|
|
30
|
-
`PgCheck`, parses command-line options via `self.parsing_input`, and
|
|
31
|
-
dispatches to the appropriate action handler (`add_check_info`,
|
|
32
|
-
`process_check`, `get_check_info`, `set_dscheck_options`, ...).
|
|
33
|
-
Build new actions by adding a method here and routing to it from
|
|
34
|
-
`start_actions()`.
|
|
35
|
-
|
|
36
|
-
- **`pg_check.py`** — defines the `PgCheck` class (inherits from
|
|
37
|
-
`PgCMD` in `rda_python_common`). Holds the master `OPTS` option
|
|
38
|
-
table, the `ALIAS` map for long/alias names, the `TBLHASH` table
|
|
39
|
-
field maps for `dscheck` and `dsdaemon`, and the helper methods
|
|
40
|
-
shared by every action (option validation, dynamic batch-option
|
|
41
|
-
resolution, daemon control, host/specialist resolution, etc.).
|
|
42
|
-
Add or change options here, then document them in `dscheck.usg`.
|
|
43
|
-
|
|
44
|
-
- **`dscheck.usg`** — single source of truth for the user-facing
|
|
45
|
-
documentation displayed by `dscheck -?` and rendered as the
|
|
46
|
-
[user guide](https://gdex-docs-dscheck.readthedocs.io). Section 3
|
|
47
|
-
lists Action options, Section 4 lists Mode options, and Section 5
|
|
48
|
-
lists Single- and Multi-Value Info options. When you add a new
|
|
49
|
-
option to `OPTS` in `pg_check.py`, add a matching entry to the
|
|
50
|
-
appropriate subsection of this file and (if relevant) to the
|
|
51
|
-
per-action usage block in Section 3.
|
|
52
|
-
|
|
53
|
-
### Installing from PyPI
|
|
54
|
-
|
|
55
|
-
The package is published on [PyPI](https://pypi.org/project/rda_python_dscheck/),
|
|
56
|
-
so the regular install command is:
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
pip install rda_python_dscheck
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
To upgrade an existing install to the latest published release:
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
pip install --upgrade rda_python_dscheck
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
This pulls in `rda_python_common` (which provides `PgCMD`, `PgLOG`,
|
|
69
|
-
`PgDBI`, ...) and registers the `setuid_dscheck` console script.
|
|
70
|
-
|
|
71
|
-
### Installing for development
|
|
72
|
-
|
|
73
|
-
For local changes, clone the repo and install in editable mode so that
|
|
74
|
-
edits are picked up immediately without reinstalling:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
git clone https://github.com/NCAR/rda-python-dscheck.git
|
|
78
|
-
cd rda-python-dscheck
|
|
79
|
-
pip install -e .
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Documentation sync
|
|
83
|
-
|
|
84
|
-
The user guide rendered at
|
|
85
|
-
[gdex-docs-dscheck.readthedocs.io](https://gdex-docs-dscheck.readthedocs.io) is
|
|
86
|
-
generated from `src/rda_python_dscheck/dscheck.usg` in this repository. When a
|
|
87
|
-
pull request that modifies `dscheck.usg` is merged here, an automated workflow
|
|
88
|
-
converts the updated `dscheck.usg` into the RST-format source files in the
|
|
89
|
-
[gdex-docs-dscheck](https://github.com/NCAR/gdex-docs-dscheck) repository and
|
|
90
|
-
opens a pull request there with the regenerated docs, ready for review and
|
|
91
|
-
merge. No manual RST editing is required — keep all user-facing content in
|
|
92
|
-
`dscheck.usg` and let the sync produce the docs.
|
|
93
|
-
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
rda_python_dscheck/PgCheck.py,sha256=lvh0XSWJID9J9fjqmDtpq6xW2ULC-bChAxAkm8MFzbk,64217
|
|
2
|
-
rda_python_dscheck/__init__.py,sha256=4Wtgj9ephcxz20cPTI4SZ_XCuCM0oqtfq9wL8kcVr3Y,734
|
|
3
|
-
rda_python_dscheck/ds_check.py,sha256=-js5Ex1k7V8ziE_k-ld5Z0l44QGYhvQtdYri9vsqNJA,24303
|
|
4
|
-
rda_python_dscheck/dscheck.py,sha256=-vv7gw4xYIa1xofWo-o3972dDnR_FQZxZz6_S_kCCuk,24805
|
|
5
|
-
rda_python_dscheck/dscheck.usg,sha256=zvghJK0XKXlSNopI1G8PYorRVUkpXoZLmFWQGqGAmBQ,31662
|
|
6
|
-
rda_python_dscheck/pg_check.py,sha256=ftmXSGXWeusQPV9FA6-3_fzhbfDCGfDIgjAK5yxi2jA,67476
|
|
7
|
-
rda_python_dscheck-2.0.8.dist-info/licenses/LICENSE,sha256=1dck4EAQwv8QweDWCXDx-4Or0S8YwiCstaso_H57Pno,1097
|
|
8
|
-
rda_python_dscheck-2.0.8.dist-info/METADATA,sha256=WDn3PoFKAR6BkmOE16Rfhz9Hbt2kw4mAwm_GyZTZfpE,3689
|
|
9
|
-
rda_python_dscheck-2.0.8.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
10
|
-
rda_python_dscheck-2.0.8.dist-info/entry_points.txt,sha256=frVByX3Vp_Pd_zq93SXfItr5OMTd5tKeZzu5pbVXiGA,60
|
|
11
|
-
rda_python_dscheck-2.0.8.dist-info/top_level.txt,sha256=NrvWqcHMRlQZJb0w85JrDlSXTp9DF-pDRQaAEABzFts,19
|
|
12
|
-
rda_python_dscheck-2.0.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|