rda-python-metrics 1.0.4__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-metrics might be problematic. Click here for more details.

Files changed (47) hide show
  1. rda_python_metrics/PgIPInfo.py +188 -0
  2. rda_python_metrics/PgView.py +782 -0
  3. rda_python_metrics/__init__.py +1 -0
  4. rda_python_metrics/fillawsusage.py +282 -0
  5. rda_python_metrics/fillawsusage.usg +17 -0
  6. rda_python_metrics/fillcodusage.py +247 -0
  7. rda_python_metrics/fillcodusage.usg +21 -0
  8. rda_python_metrics/fillcountry.py +79 -0
  9. rda_python_metrics/fillendtime.py +93 -0
  10. rda_python_metrics/fillglobususage.py +287 -0
  11. rda_python_metrics/fillglobususage.usg +17 -0
  12. rda_python_metrics/fillipinfo.py +185 -0
  13. rda_python_metrics/fillipinfo.usg +18 -0
  14. rda_python_metrics/filloneorder.py +155 -0
  15. rda_python_metrics/filloneorder.usg +41 -0
  16. rda_python_metrics/fillrdadb.py +151 -0
  17. rda_python_metrics/fillrdadb.usg +32 -0
  18. rda_python_metrics/filltdsusage.py +289 -0
  19. rda_python_metrics/filltdsusage.usg +17 -0
  20. rda_python_metrics/filluser.py +216 -0
  21. rda_python_metrics/filluser.usg +16 -0
  22. rda_python_metrics/logarch.py +359 -0
  23. rda_python_metrics/logarch.usg +27 -0
  24. rda_python_metrics/pgperson.py +72 -0
  25. rda_python_metrics/pgusername.py +50 -0
  26. rda_python_metrics/viewallusage.py +350 -0
  27. rda_python_metrics/viewallusage.usg +198 -0
  28. rda_python_metrics/viewcheckusage.py +289 -0
  29. rda_python_metrics/viewcheckusage.usg +185 -0
  30. rda_python_metrics/viewcodusage.py +314 -0
  31. rda_python_metrics/viewcodusage.usg +184 -0
  32. rda_python_metrics/viewordusage.py +340 -0
  33. rda_python_metrics/viewordusage.usg +224 -0
  34. rda_python_metrics/viewrqstusage.py +362 -0
  35. rda_python_metrics/viewrqstusage.usg +217 -0
  36. rda_python_metrics/viewtdsusage.py +323 -0
  37. rda_python_metrics/viewtdsusage.usg +191 -0
  38. rda_python_metrics/viewwebfile.py +294 -0
  39. rda_python_metrics/viewwebfile.usg +212 -0
  40. rda_python_metrics/viewwebusage.py +371 -0
  41. rda_python_metrics/viewwebusage.usg +211 -0
  42. rda_python_metrics-1.0.4.dist-info/METADATA +18 -0
  43. rda_python_metrics-1.0.4.dist-info/RECORD +47 -0
  44. rda_python_metrics-1.0.4.dist-info/WHEEL +5 -0
  45. rda_python_metrics-1.0.4.dist-info/entry_points.txt +22 -0
  46. rda_python_metrics-1.0.4.dist-info/licenses/LICENSE +21 -0
  47. rda_python_metrics-1.0.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ ###############################################################################
4
+ #
5
+ # Title : filluser
6
+ # Author : Zaihua Ji, zji@ucar.edu
7
+ # Date : 02/15/2024
8
+ # 2025-03-26 transferred to package rda_python_metrics from
9
+ # https://github.com/NCAR/rda-database.git
10
+ # Purpose : python functions to retrieve info from Oracle database and fill
11
+ # table user in PostgreSQL database.schema rdadb.dssdb.
12
+ #
13
+ # Github : https://github.com/NCAR/rda-python-metrics.git
14
+ #
15
+ ###############################################################################
16
+ import sys
17
+ import re
18
+ import time
19
+ from os import path as op
20
+ from rda_python_common import PgLOG
21
+ from rda_python_common import PgUtil
22
+ from rda_python_common import PgDBI
23
+
24
+ TBNAME = 'dssdb.user'
25
+
26
+ #
27
+ # main function to run this program
28
+ #
29
+ def main():
30
+
31
+ argv = sys.argv[1:]
32
+ missed = False
33
+ userno = logname = option = None
34
+
35
+ for arg in argv:
36
+ if arg == "-b":
37
+ PgLOG.PGLOG['BCKGRND'] = 1
38
+ elif re.match(r'^-[inu]$', arg):
39
+ option = arg[1]
40
+ if option == 'i':
41
+ missed = True
42
+ option = None
43
+ elif arg[0] == '-':
44
+ PgLOG.pglog(arg + ": Invalid Option", PgLOG.LGWNEX)
45
+ elif option == "n":
46
+ userno = arg
47
+ option = None
48
+ elif option == "u":
49
+ logname = arg
50
+ option = None
51
+ else:
52
+ PgLOG.pglog(arg + ": Invalid Parameter", PgLOG.LGWNEX)
53
+
54
+ if not (missed or userno or logname): PgLOG.show_usage('filluser')
55
+
56
+ if not PgLOG.valid_command("pgperson"):
57
+ errmsg = PgLOG.PGLOG['SYSERR'] if PgLOG.PGLOG['SYSERR'] else "Cannot find command"
58
+ PgLOG.pglog("filluser: Cannot be executed on '{}'\n{}".format(PgLOG.PGLOG['HOSTNAME'], errmsg), PgLOG.LGWNEX)
59
+
60
+ PgDBI.dssdb_scname()
61
+ PgLOG.cmdlog("filluser {}".format(' '.join(argv)))
62
+ if missed: # checking and fill missed ones in user table
63
+ fill_missed_users()
64
+ else:
65
+ fill_one_user(userno, logname)
66
+
67
+ sys.exit(0)
68
+
69
+ #
70
+ # update users with missed info in table dssdb.user
71
+ #
72
+ def fill_missed_users():
73
+
74
+ PgLOG.pglog("Getting incomplete user info", PgLOG.LOGWRN)
75
+ pgusers = PgDBI.pgmget(TBNAME, "*", "stat_flag = 'M'", PgLOG.LOGWRN)
76
+ cntall = len(pgusers['logname']) if pgusers else 0
77
+ s = 's' if cntall > 1 else ''
78
+ PgLOG.pglog("{} record{} retrieved at {}".format(cntall, s, PgLOG.current_datetime()), PgLOG.LOGWRN)
79
+ if not cntall: return
80
+ modcnt = 0
81
+ for i in range(cntall):
82
+ pgrec = PgUtil.onerecord(pgusers, i)
83
+ record = PgDBI.ucar_user_info(pgrec['userno'], pgrec['logname'])
84
+ if record:
85
+ modcnt += PgDBI.pgupdt(TBNAME, record, "uid = {}".format(pgrec['uid']), PgLOG.LOGWRN)
86
+
87
+ if (i%500) == 499:
88
+ PgLOG.pglog("{}/{} Records modifiled/processed".format(modcnt, (i+1)), PgLOG.WARNLG)
89
+ s = 's' if modcnt > 1 else ''
90
+ PgLOG.pglog("{} User Record{} modified".format(modcnt, s), PgLOG.LOGWRN)
91
+ return modcnt
92
+
93
+ #
94
+ # Fill one user for given condition userno or logname
95
+ #
96
+ def fill_one_user(userno, logname):
97
+
98
+ if userno:
99
+ msg = "User ID {}: ".format(userno)
100
+ else:
101
+ msg = "User Login Name {}: ".format(logname)
102
+ modcnt = cntadd = 0
103
+ newrec = PgDBI.ucar_user_info(userno, logname)
104
+ if not newrec:
105
+ PgLOG.pglog(msg + "No User info found from People DB", PgLOG.LOGWRN)
106
+ return
107
+
108
+ cond = 'userno = {}'.format(userno) if userno else "logname = '{}'".format(logname)
109
+ pgrec = PgDBI.pgget(TBNAME, "*", cond + " AND until_date is null", PgLOG.LGWNEX)
110
+ record = get_user_record(newrec, pgrec, (newrec['stat_flag'] == 'A'))
111
+ if record == None:
112
+ PgLOG.pglog(msg + "User record saved already", PgLOG.LOGWRN)
113
+ return
114
+ if record:
115
+ if pgrec:
116
+ if PgDBI.pgupdt(TBNAME, record, "uid = {}".format(pgrec['uid']), PgLOG.LOGWRN):
117
+ PgLOG.pglog(msg + "Existing User record Modified", PgLOG.LOGWRN)
118
+ modcnt += 1
119
+ else:
120
+ if PgDBI.pgadd(TBNAME, record, PgLOG.LGWNEX):
121
+ PgLOG.pglog(msg + "New user record added", PgLOG.LOGWRN)
122
+ cntadd += 1
123
+ else:
124
+ record = {'stat_flag' : 'C'}
125
+ record['until_date'] = PgUtil.adddate(newrec['start_date'], 0, 0, -1)
126
+ if PgDBI.pgupdt(TBNAME, record, "uid = {}".format(pgrec['uid']), PgLOG.LOGWRN):
127
+ PgLOG.pglog(msg + "Existing User record Closed", PgLOG.LOGWRN)
128
+ modcnt += 1
129
+
130
+ record = get_user_record(newrec)
131
+ if record and PgDBI.pgadd(TBNAME, record, PgLOG.LGWNEX):
132
+ PgLOG.pglog(msg + "Additional New user record added", PgLOG.LOGWRN)
133
+ cntadd += 1
134
+
135
+ #
136
+ # local function: get_user_record(orarec: refer to oracle hush record
137
+ # pgrecs: refer to exist, mysql hush records)
138
+
139
+ # return: a reference to a new mysql record for update or add
140
+ #
141
+ def get_user_record(orarec, pgrec = None, neworg = False):
142
+
143
+ if not orarec['email']: return None
144
+
145
+ ms = re.match("^(.+\@).+\.ucar\.edu$", orarec['email'], re.I)
146
+ if ms: orarec['email'] = ms.group(1) + "ucar.edu"
147
+
148
+ newrec = {}
149
+ if pgrec:
150
+ if neworg and PgUtil.diffdate(orarec['start_date'], pgrec['start_date']) <= 0:
151
+ neworg = False
152
+ if not pgrec['division'] or pgrec['division'] != orarec['division']:
153
+ if neworg and orarec['org_type'] == 'NCAR': return 0
154
+ newrec['division'] = orarec['division']
155
+ if orarec['org_name'] and (not pgrec['org_name'] or pgrec['org_name'] != orarec['org_name']):
156
+ if neworg: return 0
157
+ newrec['org_name'] = orarec['org_name']
158
+ if orarec['country'] and (not pgrec['country'] or orarec['country'] and pgrec['country'] != orarec['country']):
159
+ orarec['country'] = PgDBI.set_country_code(orarec)
160
+ if not pgrec['country'] or pgrec['country'] != orarec['country']:
161
+ if neworg: return 0
162
+ newrec['country'] = orarec['country']
163
+ if not pgrec['org_type'] or (orarec['org_type'] and pgrec['org_type'] != orarec['org_type']):
164
+ orarec['org_type'] = PgDBI.get_org_type(orarec['org_type'], orarec['email'])
165
+ if not pgrec['org_type'] or pgrec['org_type'] != orarec['org_type']:
166
+ if neworg: return 0
167
+ newrec['org_type'] = orarec['org_type']
168
+ if not pgrec['email'] or pgrec['email'] != orarec['email']:
169
+ if neworg: return 0
170
+ newrec['email'] = orarec['email']
171
+ if not pgrec['ucaremail'] or pgrec['ucaremail'] != orarec['ucaremail']:
172
+ newrec['ucaremail'] = orarec['ucaremail']
173
+ if 'until_date' in orarec and PgUtil.diffdate(pgrec['until_date'], orarec['until_date']):
174
+ newrec['until_date'] = orarec['until_date']
175
+ if not pgrec['userno'] or pgrec['userno'] != orarec['userno']:
176
+ newrec['userno'] = orarec['userno']
177
+ if not pgrec['upid'] or pgrec['upid'] != orarec['upid']:
178
+ newrec['upid'] = orarec['upid']
179
+ if not pgrec['logname'] or pgrec['logname'] != orarec['logname']:
180
+ newrec['logname'] = orarec['logname']
181
+ if orarec['lstname'] and (not pgrec['lstname'] or pgrec['lstname'] != orarec['lstname']):
182
+ newrec['lstname'] = orarec['lstname']
183
+ if orarec['fstname'] and (not pgrec['fstname'] or pgrec['fstname'] != orarec['fstname']):
184
+ newrec['fstname'] = orarec['fstname']
185
+ if pgrec['stat_flag'] != orarec['stat_flag']:
186
+ newrec['stat_flag'] = orarec['stat_flag']
187
+ if 'phoneno' in orarec and orarec['phoneno'] and (not pgrec['phoneno'] or pgrec['phoneno'] != orarec['phoneno']):
188
+ newrec['phoneno'] = orarec['phoneno']
189
+ if 'faxno' in orarec and orarec['faxno'] and (not pgrec['faxno'] or pgrec['faxno'] != orarec['faxno']):
190
+ newrec['faxno'] = orarec['faxno']
191
+ if orarec['start_date'] and (not pgrec['start_date'] or PgUtil.diffdate(pgrec['start_date'], orarec['start_date']) > 0):
192
+ newrec['start_date'] = orarec['start_date']
193
+ elif orarec['stat_flag'] == 'A':
194
+ newrec['upid'] = orarec['upid']
195
+ newrec['userno'] = orarec['userno']
196
+ newrec['logname'] = orarec['logname']
197
+ newrec['lstname'] = orarec['lstname']
198
+ newrec['fstname'] = orarec['fstname']
199
+ newrec['stat_flag'] = orarec['stat_flag']
200
+ if orarec['start_date']: newrec['start_date'] = orarec['start_date']
201
+ if 'until_date' in orarec: newrec['until_date'] = orarec['until_date']
202
+ newrec['division'] = orarec['division']
203
+ newrec['org_name'] = orarec['org_name']
204
+ newrec['org_type'] = PgDBI.get_org_type(orarec['org_type'], orarec['email'])
205
+ newrec['country'] = PgDBI.set_country_code(orarec['email'], orarec['country'])
206
+ newrec['email'] = orarec['email']
207
+ newrec['ucaremail'] = orarec['ucaremail']
208
+ if 'phoneno' in orarec: newrec['phoneno'] = orarec['phoneno']
209
+ if 'faxno' in orarec: newrec['faxno'] = orarec['faxno']
210
+
211
+ return newrec if newrec else None
212
+
213
+ #
214
+ # call main() to start program
215
+ #
216
+ if __name__ == "__main__": main()
@@ -0,0 +1,16 @@
1
+
2
+ Retrieves user information from ORACLE SERVER and fill
3
+ table 'user' in MySQL database 'dssdb'.
4
+
5
+ Usage: filluser [-b] [-i] [-n UserNumber] [-u UserLonginName]
6
+
7
+ select one of the options, -i, -n or -u each time to run this application.
8
+
9
+ - Option -b, log process information into logfile only;
10
+
11
+ - Option -i, get users with incomplete information in 'dssdb.user';
12
+
13
+ - Option -n, get users by their user numbers on NCAR system;
14
+
15
+ - Option -u, get users by their login names on NCAR system;
16
+
@@ -0,0 +1,359 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ ##################################################################################
4
+ #
5
+ # Title : logarch
6
+ # Author : Zaihua Ji, zji@ucar.edu
7
+ # Date : 11/19/2020
8
+ # 2025-03-26 transferred to package rda_python_metrics from
9
+ # https://github.com/NCAR/rda-utility-programs.git
10
+ # Purpose : archive log files automatically
11
+ #
12
+ # Github : https://github.com/NCAR/rda-python-metrics.git
13
+ #
14
+ ##################################################################################
15
+
16
+ import sys
17
+ import re
18
+ from os import path as op
19
+ import glob
20
+ from rda_python_common import PgLOG
21
+ from rda_python_common import PgUtil
22
+ from rda_python_common import PgFile
23
+ from rda_python_common import PgSIG
24
+
25
+ # the defined options for archiving different logs
26
+ WLOG = 0x01 # archive web log
27
+ TLOG = 0x02 # archive tds log
28
+ DLOG = 0x04 # archive dssdb logs
29
+ SLOG = 0x08 # append dssdb sub batch logs
30
+ ALOG = 0x10 # archive AWS web log
31
+
32
+ LOGS = {
33
+ 'OPTION' : 0,
34
+ 'AWSLOG' : PgLOG.PGLOG["TRANSFER"] + "/AWSera5log",
35
+ 'WEBLOG' : PgLOG.PGLOG["DSSDATA"] + "/work/logs/gridftp",
36
+ 'MGTLOG' : "/data/logs",
37
+ 'TDSLOG' : "/data/logs/nginx",
38
+ 'RDALOG' : PgLOG.PGLOG['LOGPATH'],
39
+ 'LOGPATH' : None,
40
+ 'CHKLOG' : 1,
41
+ 'DECSLOGS' : PgLOG.PGLOG['DECSHOME'] + "/DECSLOGS"
42
+ }
43
+
44
+ BIDS = {}
45
+
46
+ #
47
+ # main function to excecute this script
48
+ #
49
+ def main():
50
+
51
+ pgname = "logarch"
52
+ argv = sys.argv[1:]
53
+ smonth = None
54
+
55
+ # set different log file
56
+ PgLOG.PGLOG['LOGFILE'] = pgname + '.log'
57
+ PgLOG.set_suid(PgLOG.PGLOG['EUID'])
58
+
59
+ option = None
60
+ for arg in argv:
61
+ ms = re.match(r'^-([abdmnpstw])', arg)
62
+ if ms:
63
+ option = ms.group(1)
64
+ if option in 'mp': continue
65
+ if option == "b":
66
+ PgLOG.PGLOG['BCKGRND'] = 1
67
+ elif option == "d":
68
+ LOGS['OPTION'] |= DLOG
69
+ elif option == "w":
70
+ LOGS['OPTION'] |= WLOG
71
+ elif option == "a":
72
+ LOGS['OPTION'] |= ALOG
73
+ elif option == "s":
74
+ LOGS['OPTION'] |= SLOG
75
+ elif option == "t":
76
+ LOGS['OPTION'] |= TLOG
77
+ elif option == "n":
78
+ LOGS['CHKLOG'] = 0
79
+ option = None
80
+ elif option == 'm':
81
+ smonth = arg
82
+ elif option == 'p':
83
+ LOGS['LOGPATH'] = arg
84
+ else:
85
+ PgLOG.pglog(arg + ": Invalid Option", PgLOG.LGWNEX)
86
+ option = None
87
+
88
+ if not LOGS['OPTION']: PgLOG.show_usage(pgname)
89
+ PgLOG.cmdlog("{} {}".format(pgname, ' '.join(argv)))
90
+
91
+ if LOGS['OPTION']&SLOG: append_dssdb_sublog()
92
+ if LOGS['OPTION']&DLOG: archive_dssdb_log()
93
+ if LOGS['OPTION']&WLOG: archive_web_log(smonth)
94
+ if LOGS['OPTION']&ALOG: archive_aws_log(smonth)
95
+ if LOGS['OPTION']&TLOG: archive_tds_log(smonth)
96
+
97
+ PgLOG.cmdlog(None, 0, PgLOG.LOGWRN|PgLOG.SNDEML)
98
+ PgLOG.pgexit(0)
99
+
100
+ def get_year_month(smonth):
101
+
102
+ if not smonth: smonth = PgUtil.adddate(PgUtil.curdate('YYYY-MM') + '-01', 0, -1, 0, 'YYYY-MM')
103
+ ms = re.match(r'^(\d+)-(\d+)', smonth)
104
+ return [ms.group(1), '{:02}'.format(int(ms.group(2)))]
105
+
106
+ #
107
+ # Archive globus web log files to LOGS['DECSLOGS']
108
+ #
109
+ def archive_web_log(smonth):
110
+
111
+ (yr, mn) = get_year_month(smonth)
112
+ PgFile.change_local_directory(LOGS['DECSLOGS'], PgLOG.LGEREM)
113
+ logpath = LOGS['LOGPATH'] if LOGS['LOGPATH'] else LOGS['WEBLOG']
114
+ afile = "globusweb{}-{}.log.tar".format(yr, mn)
115
+ dfile = "./WEBLOG/{}.gz".format(afile)
116
+ if op.exists(dfile):
117
+ PgLOG.pglog("{}: file exists already under {}, remove it before backup again".format(dfile, LOGS['DECSLOGS']), PgLOG.LGWNEM)
118
+ return
119
+
120
+ if op.exists(afile): PgFile.delete_local_file(afile)
121
+
122
+ logfiles = sorted(glob.glob("{}/access_log_gridftp??_{}??{}".format(logpath, mn, yr)))
123
+ topt = '-cvf'
124
+ tcnt = 0
125
+ for logfile in logfiles:
126
+ if not op.exists(logfile):
127
+ PgLOG.pglog(logfile + ": file not exists", PgLOG.LGWNEM)
128
+ continue
129
+ if op.getsize(logfile) == 0:
130
+ PgLOG.pglog(logfile + ": empty file", PgLOG.LGWNEM)
131
+ continue
132
+ lfile = op.basename(logfile)
133
+ tcmd = "tar {} {} -C {} {}".format(topt, afile, logpath, lfile)
134
+ tcnt += PgLOG.pgsystem(tcmd, PgLOG.LGWNEM, 5)
135
+ topt = '-uvf'
136
+
137
+
138
+ if tcnt > 0:
139
+ PgLOG.pgsystem("gzip " + afile, PgLOG.LGWNEM, 5)
140
+ afile += '.gz'
141
+ PgFile.move_local_file(dfile, afile, PgLOG.LGWNEM)
142
+ s = 's' if tcnt > 1 else ''
143
+ PgLOG.pglog("{}: {} globus log{} tarred, gzipped and archived at {}".format(afile, tcnt, s, PgLOG.current_datetime()), PgLOG.LGWNEM)
144
+
145
+ #
146
+ # Archive AWS web log files to LOGS['DECSLOGS']
147
+ #
148
+ def archive_aws_log(smonth):
149
+
150
+ (yr, mn) = get_year_month(smonth)
151
+ PgFile.change_local_directory(LOGS['DECSLOGS'], PgLOG.LGEREM)
152
+ logpath = LOGS['LOGPATH'] if LOGS['LOGPATH'] else LOGS['AWSLOG']
153
+ afile = "awsweb{}-{}.log.tar".format(yr, mn)
154
+ dfile = "./AWSLOG/{}.gz".format(afile)
155
+ if op.exists(dfile):
156
+ PgLOG.pglog("{}: file exists already under {}, remove it before backup again".format(dfile, LOGS['DECSLOGS']), PgLOG.LGWNEM)
157
+ return
158
+
159
+ if op.exists(afile): PgFile.delete_local_file(afile)
160
+
161
+ lfile = "{}/{}".format(yr, mn)
162
+ tcmd = "tar -cvf {} -C {} {}".format(afile, logpath, lfile)
163
+ PgLOG.pgsystem(tcmd, PgLOG.LGWNEM, 5)
164
+
165
+ PgLOG.pgsystem("gzip " + afile, PgLOG.LGWNEM, 5)
166
+ afile += '.gz'
167
+ PgFile.move_local_file(dfile, afile, PgLOG.LGWNEM)
168
+ PgLOG.pglog("{}: AWS logs tarred, gzipped and archived at {}".format(afile, PgLOG.current_datetime()), PgLOG.LGWNEM)
169
+
170
+ #
171
+ # Archive monthly tds logs under DECSLOGS/TDSLOG/
172
+ #
173
+ def archive_tds_log(smonth):
174
+
175
+ (yr, mn) = get_year_month(smonth)
176
+ PgFile.change_local_directory(LOGS['DECSLOGS'], PgLOG.LGEREM)
177
+ logpath = LOGS['LOGPATH'] if LOGS['LOGPATH'] else LOGS['TDSLOG']
178
+ afile = "thredds{}-{}.log.tar".format(yr, mn)
179
+ dfile = "./TDSLOG/{}.gz".format(afile)
180
+ if op.exists(dfile):
181
+ PgLOG.pglog("{}: file exists already under {}, remove it before backup again".format(dfile, LOGS['DECSLOGS']), PgLOG.LGWNEM)
182
+ return
183
+
184
+ if op.exists(afile): PgFile.delete_local_file(afile)
185
+
186
+ logfiles = sorted(glob.glob("{}/{}-{}-??.access.log".format(logpath, yr, mn)))
187
+ topt = '-cvf'
188
+ tcnt = 0
189
+ for logfile in logfiles:
190
+ if not op.exists(logfile):
191
+ PgLOG.pglog(logfile + ": file not exists", PgLOG.LGWNEM)
192
+ continue
193
+ if op.getsize(logfile) == 0:
194
+ PgLOG.pglog(logfile + ": empty file", PgLOG.LGWNEM)
195
+ continue
196
+ lfile = op.basename(logfile)
197
+ tcmd = "tar {} {} -C {} {}".format(topt, afile, logpath, lfile)
198
+ tcnt += PgLOG.pgsystem(tcmd, PgLOG.LGWNEM, 5)
199
+ topt = '-uvf'
200
+
201
+ if tcnt > 0:
202
+ PgLOG.pgsystem("gzip " + afile, PgLOG.LGWNEM, 5)
203
+ afile += '.gz'
204
+ PgFile.move_local_file(dfile, afile, PgLOG.LGWNEM)
205
+ s = 's' if tcnt > 1 else ''
206
+ PgLOG.pglog("{}: {} thredds log{} tarred, gzipped and archived at {}".format(afile, tcnt, s, PgLOG.current_datetime()), PgLOG.LGWNEM)
207
+
208
+ #
209
+ # Archive current dssdb logs onto hpss under /DSS/RDADB/LOG
210
+ #
211
+ def archive_dssdb_log():
212
+
213
+ cntall = 0
214
+ logfile = "{}_dblog{}.tar".format(PgLOG.PGLOG['HOSTNAME'], PgUtil.curdate("YYMMDD"))
215
+ dfile = "{}/RDADB/LOG/{}.gz".format(LOGS['DECSLOGS'], logfile)
216
+ if LOGS['CHKLOG'] and check_decs_archive(dfile):
217
+ return PgLOG.pglog(dfile + ": archived already", PgLOG.LGWNEM)
218
+
219
+ PgFile.change_local_directory(LOGS['RDALOG'], PgLOG.LWEMEX)
220
+
221
+ # collect all the large log/err files
222
+ files = sorted(glob.glob("*.log") + glob.glob("*.err"))
223
+ for file in files:
224
+ info = PgFile.check_local_file(file, 2)
225
+ if(not info or info['data_size'] < 10000): continue # skip log files small than 10KB
226
+
227
+ PgLOG.pgsystem("cp -p -f {} backup/{}".format(file, file), PgLOG.LWEMEX, 5)
228
+ if info['logname'] != PgLOG.PGLOG['RDAUSER']: PgLOG.pgsystem("rm -rf " + file)
229
+ PgLOG.pgsystem("cat /dev/null > " + file, 0, 1024)
230
+ if op.exists(logfile):
231
+ PgLOG.pgsystem("tar -uvf {} -C backup {}".format(logfile, file), PgLOG.LWEMEX, 5)
232
+ else:
233
+ PgLOG.pgsystem("tar -cvf {} -C backup {}".format(logfile, file), PgLOG.LWEMEX, 5)
234
+ cntall += 1
235
+
236
+ if cntall > 0:
237
+ if LOGS['CHKLOG']:
238
+ if backup_decsdata_file(logfile, logfile, dfile, 1):
239
+ s = 's' if cntall > 1 else ''
240
+ PgLOG.pglog("{} dssdb log{} archived at {}".format(cntall, s, PgLOG.current_datetime()), PgLOG.LGWNEM)
241
+ else:
242
+ PgLOG.pgsystem("gzip " + logfile, PgLOG.LWEMEX, 5)
243
+ logfile += ".gz"
244
+ PgLOG.pgsystem("mv -f {} backup/".format(logfile), PgLOG.LWEMEX, 5)
245
+
246
+ #
247
+ # append individual batch logs to common stdout/error logs
248
+ #
249
+ def append_dssdb_sublog():
250
+
251
+ logpath = LOGS['LOGPATH'] if LOGS['LOGPATH'] else LOGS['RDALOG']
252
+ PgFile.change_local_directory(logpath, PgLOG.LGWNEX);
253
+
254
+ if not PgLOG.valid_command(PgLOG.BCHCMDS['PBS']):
255
+ PgLOG.pglog("Must run on PBS Nodes to append sublogs", PgLOG.LGEREM)
256
+ return
257
+
258
+ add_sublog_files('OU', 'log')
259
+ add_sublog_files('ER', 'err', 37)
260
+
261
+ #
262
+ # add individual sublog files to the common ones
263
+ #
264
+ def add_sublog_files(fext, sext, minsize = 0):
265
+
266
+ subname = 'rdaqsub'
267
+ pattern = r'^(\d+)\.'
268
+ afiles = PgFile.local_glob("{}/*.{}".format(subname, fext), 3, PgLOG.LGWNEX)
269
+ if not afiles:
270
+ PgLOG.pglog("{}: NO '{}' file found to collect".format(subname, fext), PgLOG.LOGWRN)
271
+ return
272
+ if minsize:
273
+ tmin = PgLOG.PGLOG['MINSIZE']
274
+ PgLOG.PGLOG['MINSIZE'] = minsize
275
+ acnt = fcnt = 0
276
+ sfiles = {}
277
+ for afile in afiles:
278
+ fcnt += 1
279
+ finfo = afiles[afile]
280
+ sfiles[op.basename(afile)] = "{} {} {}".format(finfo['date_modified'], finfo['time_modified'], finfo['logname'])
281
+
282
+ afiles = sorted(sfiles)
283
+ logfile = "PBS_sublog.{}".format(sext)
284
+ for afile in afiles:
285
+ ms = re.match(pattern, afile)
286
+ if ms:
287
+ bid = int(ms.group(1))
288
+ if bid not in BIDS: BIDS[bid] = PgSIG.check_pbs_process(bid, afile)
289
+ if BIDS[bid] > 0: continue
290
+ else:
291
+ continue
292
+
293
+ sfile = "{}/{}".format(subname, afile)
294
+ if minsize and PgFile.local_file_size(sfile, 1) < 1: continue
295
+ PgLOG.pgsystem("echo '{}: {}' >> {}".format(bid, sfiles[afile], logfile), PgLOG.LGWNEX, 5+1024)
296
+ PgLOG.pgsystem("cat {} >> {}".format(sfile, logfile), PgLOG.LGWNEX, 5+1024)
297
+ PgFile.delete_local_file(sfile, PgLOG.LOGWRN)
298
+ acnt += 1
299
+ if fcnt > 0:
300
+ s = 's' if fcnt > 1 else ''
301
+ PgLOG.pglog("{}: {} of {} '{}' file{} appended at {}".format(logfile, acnt, fcnt, fext, s, PgLOG.current_datetime()), PgLOG.LOGWRN)
302
+
303
+ if minsize: PgLOG.PGLOG['MINSIZE'] = tmin
304
+
305
+ #
306
+ # backup a log file to decsdata area
307
+ #
308
+ def backup_decsdata_file(logfile, locfile, dfile, skipcheck = 0):
309
+
310
+ ret = 0
311
+ if op.getsize(logfile) == 0:
312
+ PgLOG.pglog(logfile + ": Empty log file", PgLOG.LGWNEM)
313
+ return 0
314
+ if not skipcheck and check_decs_archive(dfile, logfile, 1):
315
+ return 0 # archived already
316
+
317
+ if locfile != logfile:
318
+ locfile = "{}/{}".format(PgLOG.PGLOG['TMPPATH'], locfile)
319
+ if not PgFile.local_copy_local(locfile, logfile, PgLOG.LGWNEM): return 0
320
+ lfile = locfile
321
+ locfile += ".gz"
322
+ if PgFile.check_local_file(locfile, 0, PgLOG.LGWNEM): PgFile.delete_local_file(locfile, PgLOG.LGWNEM)
323
+ PgLOG.pgsystem("gzip " + lfile, PgLOG.LWEMEX, 5)
324
+
325
+ PgLOG.pglog("archive {} to {}".format(locfile, dfile), PgLOG.LGWNEM)
326
+ if PgFile.local_copy_local(dfile, locfile, PgLOG.LGWNEM):
327
+ size = check_decs_archive(dfile)
328
+ if size:
329
+ PgLOG.pglog("{}: archived as {}({})".format(logfile, dfile, size), PgLOG.LGWNEM)
330
+ ret = 1
331
+
332
+ if op.exists(locfile) and ret: PgLOG.pgsystem("rm -f " + locfile, PgLOG.LGWNEM)
333
+
334
+ return ret
335
+
336
+ #
337
+ # return decs file size if archived already; otherwise 0
338
+ #
339
+ def check_decs_archive(afile, logfile = None, checktime = 0):
340
+
341
+ ainfo = PgFile.check_local_file(afile, 1)
342
+ if not ainfo: return 0
343
+ size = ainfo['data_size']
344
+ if logfile:
345
+ linfo = PgFile.check_local_file(logfile, 1, PgLOG.LGWNEM)
346
+ if linfo:
347
+ if checktime:
348
+ if linfo['date_modified'] > ainfo['date_modified']: size = 0
349
+ elif size < linfo['data_size']:
350
+ size = 0
351
+
352
+ if size > 0: PgLOG.pglog("{}: archived on {} as {}({})".format(logfile, ainfo['date_modified'], afile, size), PgLOG.LGWNEM)
353
+
354
+ return size
355
+
356
+ #
357
+ # call main() to start program
358
+ #
359
+ if __name__ == "__main__": main()
@@ -0,0 +1,27 @@
1
+
2
+ Archive RDA log files onto to DECSDATA area. This application can be run
3
+ at any time. It checks if the given log files are archived or not and will
4
+ ignore the ones that are backed up already.
5
+
6
+ Usage: logarch [-b] [-a] [-d] [-w] [-s] [-t] [-p LogPath] \
7
+ [-m YearMonth] [-n]
8
+
9
+ - Option -b, do not display processing info on screen;
10
+
11
+ - Option -a, archive aws log files;
12
+
13
+ - Option -d, archive dssdb log files;
14
+
15
+ - Option -p, provide a LogPath if not the fefault one;
16
+
17
+ - Option -s, append PBS sublog files to common log files;
18
+
19
+ - Option -t, archive tds log files;
20
+
21
+ - Option -w, archive web log files;
22
+
23
+ - Option -m, Provided a specified YearMonth (in form of YYYY-MM) to backup logs;
24
+
25
+ - Option -n, do not check if a log file is backed up already;
26
+
27
+ Set at least one of the options -a, -d, -s, -t and -w to run this application.
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env python3
2
+ #*******************************************************************
3
+ # Title : pgperson.py
4
+ # Author : Zaihua Ji, zji@ucar.edu
5
+ # Date : 2025-03-27
6
+ # Purpose : utility program to retrieve user info from People DB
7
+ #
8
+ # Github : https://github.com/NCAR/rda-python-metrics.git
9
+ #
10
+ #*******************************************************************
11
+
12
+ import httplib2
13
+ import json
14
+ import sys
15
+ from rda_python_common import PgLOG
16
+
17
+ PERSON = [
18
+ "upid", # Unique person id
19
+ "username", # UCAR login user name
20
+ "email", # Email address
21
+ "uid", # Scientist id or Unix id
22
+ "firstName", # First name
23
+ "lastName", # Last name
24
+ "forwardEmail" # Forward Email address
25
+ ]
26
+
27
+ urlfmt="https://people.api.ucar.edu/persons?{}={}&searchScope=all&includeActive=true&includeInactive=true&searchType=advancedSearch"
28
+
29
+ #
30
+ # main function to excecute this script
31
+ #
32
+ def main():
33
+
34
+ pgname = "pgperson"
35
+ argv = sys.argv[1:]
36
+ optstr = '|'.join(PERSON)
37
+ if sys.argc != 3:
38
+ print("Usage: {} -({}) OptopnValue".format(pgname, optstr))
39
+ sys.exit(0)
40
+
41
+ option = optval = None
42
+ for arg in argv:
43
+ if option:
44
+ optval = arg
45
+ elif arg[0] == '-':
46
+ option = arg[1:]
47
+ if option not in PERSON:
48
+ PgLOG.pglog("{}: unknown option, must be -({})".format(arg, optstr), PgLOG.LGEREX)
49
+ else:
50
+ PgLOG.pglog("{}: Value passed in without leading option -({})".format(arg, optstr), PgLOG.LGEREX)
51
+
52
+ headers = {'Content-type': 'application/json'}
53
+ http=httplib2.Http()
54
+ url = urlfmt.format(option, optval)
55
+ response, content = http.request(url, 'GET', headers=headers)
56
+ status = response.status
57
+ if status == 200:
58
+ persons=json.loads(content)
59
+ for person in persons:
60
+ for key, value in person.items():
61
+ print("{}<=>{}".format(key, value))
62
+ elif status == 399:
63
+ print(content)
64
+ elif status == 500:
65
+ print('Server error')
66
+
67
+ sys.exit(0)
68
+
69
+ #
70
+ # call main() to start program
71
+ #
72
+ if __name__ == "__main__": main()