13
13
from sys import exit
14
14
from djangoutil .xmlrpc import getServerProxy
15
15
from xml .sax .saxutils import escape
16
-
16
+ from ConfigParser import SafeConfigParser
17
17
import codecs
18
18
import io
19
-
19
+ from django .conf import settings
20
+ from djangoutil import config
21
+ settings .configure (config )
20
22
# encoding=utf8
21
23
import sys
22
24
reload (sys )
23
25
sys .setdefaultencoding ('utf8' )
24
-
25
-
26
- from django .conf import settings
27
- from djangoutil import config
28
- settings .configure (config )
29
-
30
-
31
26
# set to UTF-8 to capture diacritics
32
27
environ ['NLS_LANG' ]= 'AMERICAN_AMERICA.AL32UTF8'
33
28
34
29
30
+
31
+ # database configuration
32
+ usedb = 'test' # choose database: dev, test, or prod
33
+ config = SafeConfigParser ()
34
+ config .read (join (getcwd (), 'fdr.config' )) # read config file to gather parameters
35
+ dbhost = config .get (usedb , 'dbhost' )
36
+ dbport = config .get (usedb , 'dbport' )
37
+ dbsid = config .get (usedb , 'dbsid' )
38
+ dbuser = config .get (usedb , 'dbuser' )
39
+ dbpassword = config .get (usedb , 'dbpassword' )
40
+
35
41
useldapforemail = False # LDAP is slow and hasn't returned significant number of emails. If False, use [email protected] instead.
36
42
sd_file = join (getcwd (), 'libsymel.dat' ) # Nightly export of Service Directory data
37
43
xmlfile = join (getcwd (), 'people.xml' ) # Output file for Symplectic Elements consumption
38
44
affiliationsfile = join (getcwd (), 'affiliations.txt' ) # Output file for unique affiliations to populate Elements Auto Groups
39
45
40
- # set text encoding to UTF-8 to capture diacritics and whatnot
41
- environ ['NLS_LANG' ]= 'AMERICAN_AMERICA.AL32UTF8'
42
-
43
- # FDR database specifics
44
- dbhost = 'fdrprd-db.oit.duke.edu'
45
- dbport = '1637'
46
- dbsid = 'FDRPRD'
47
- dbuser = 'libacct'
48
- dbpassword = 'uanbahd10'
49
-
50
46
# instantiate and configure logger
51
47
logfile = join (getcwd (), 'hrDataFeeder.log' )
52
48
logger = logging .getLogger ('fdrlogger' )
@@ -66,70 +62,80 @@ def getResults(ora, sql):
66
62
67
63
# Take list of dictionaries and build XML elements. Return string.
68
64
def buildXml (list ):
69
- sequence_dict = {1 :'Secondary' , 2 :'Tertiary' , 3 :'Quaternary' , 4 :'Quinary' , 5 :u 'Senary' , 6 :u 'Septenary' , 7 :u 'Octonary' , 8 :u 'Nonary' , 9 :u 'Denary' }
70
- xml = u ''
65
+ sequence_dict = {1 :'Secondary' , 2 :'Tertiary' , 3 :'Quaternary' , 4 :'Quinary' , 5 :'Senary' , 6 :'Septenary' , 7 :'Octonary' , 8 :'Nonary' , 9 :'Denary' }
66
+ xml = ''
71
67
for record in list :
72
- xml += u '\t \t <person>\n '
73
- xml += u '\t \t \t <Lastname>%s</Lastname>\n ' % (record [u 'surname' ])
74
- xml += u '\t \t \t <Firstname>%s</Firstname>\n ' % (record [u 'forename' ])
68
+ xml += '\t \t <person>\n '
69
+ xml += '\t \t \t <Lastname>%s</Lastname>\n ' % (record ['surname' ])
70
+ xml += '\t \t \t <Firstname>%s</Firstname>\n ' % (record ['forename' ])
75
71
try :
76
- xml += u '\t \t \t <Middlename>%s</Middlename>\n ' % (record [u 'middlename' ])
72
+ xml += '\t \t \t <Middlename>%s</Middlename>\n ' % (record ['middlename' ])
77
73
except :
78
74
pass
79
- xml += u '\t \t \t <Email>%s</Email>\n ' % (record ['email' ]) # removing angle brackets in some email fields
80
- xml += u '\t \t \t <Proprietary_ID>%s</Proprietary_ID>\n ' % (record [u 'duid' ])
81
- xml += u '\t \t \t <Username>%s</Username>\n ' % (record [u 'netid' ])
82
- xml += u '\t \t \t <PrimaryGroupDescriptor>%s</PrimaryGroupDescriptor>\n ' % (escape (record [u 'primary' ]))
75
+ xml += '\t \t \t <Email>%s</Email>\n ' % (record ['email' ]) # removing angle brackets in some email fields
76
+ xml += '\t \t \t <Proprietary_ID>%s</Proprietary_ID>\n ' % (record ['duid' ])
77
+ xml += '\t \t \t <Username>%s</Username>\n ' % (record ['netid' ])
78
+ xml += '\t \t \t <PrimaryGroupDescriptor>%s</PrimaryGroupDescriptor>\n ' % (escape (record ['primary' ]))
83
79
# this must change in response to addition of school
84
80
if 'secondary' in record :
85
- if len (record [u 'secondary' ]) > 0 :
81
+ if len (record ['secondary' ]) > 0 :
86
82
i = 1
87
- for appointment in record [u 'secondary' ]:
88
- xml += u '\t \t \t <%sGroupDescriptor>%s</%sGroupDescriptor>\n ' % (sequence_dict [i ], escape (appointment .strip ()), sequence_dict [i ])
83
+ for appointment in record ['secondary' ]:
84
+ xml += '\t \t \t <%sGroupDescriptor>%s</%sGroupDescriptor>\n ' % (sequence_dict [i ], escape (appointment .strip ()), sequence_dict [i ])
89
85
i += 1
90
- xml += u '\t \t \t <IsAcademic>%s</IsAcademic>\n ' % (record [u 'academic' ])
91
- xml += u '\t \t \t <LoginAllowed>%s</LoginAllowed>\n ' % (record [u 'login' ])
92
- xml += u '\t \t \t <AuthenticatingAuthority>%s</AuthenticatingAuthority>\n ' % (record [u 'authority' ])
93
- xml += u '\t \t </person>\n '
86
+ xml += '\t \t \t <IsAcademic>%s</IsAcademic>\n ' % (record ['academic' ])
87
+ xml += '\t \t \t <LoginAllowed>%s</LoginAllowed>\n ' % (record ['login' ])
88
+ xml += '\t \t \t <AuthenticatingAuthority>%s</AuthenticatingAuthority>\n ' % (record ['authority' ])
89
+ xml += '\t \t </person>\n '
94
90
return xml
95
91
96
92
97
93
# Build list of dictionaries of FDR people. Also return list of Duke Unique IDs.
98
94
def buildFdrDict (data , rpcserver , sd_dict_list ):
95
+ print 'buildFdrDict'
99
96
fdr_dict_list = []
100
- duid_list = []
97
+ # CHANGE THIS. DROP FDR RECORD WITHOUT NETID, USE NETID as KEY
98
+ netid_list = []
101
99
missing_fdr_email = 0
102
100
missing_email_found_sd = 0
103
101
for record in data :
104
102
drop_record = False
105
103
fdr_dict = {}
106
104
try : # Confusing. FDR forced their names on us. Their PRIMARY_SCHOOL is our primary group, all other groups are secondary for us.
107
- duid , netid , salutation , surname , forename , middlename , lsurname , lforename , lmiddlename , email , primary , school , secondary = record
105
+ duid , netid , salutation , surname , forename , middlename , lsurname , lforename , lmiddlename , email , primary , school , secondary , primary_affiliation = record
108
106
except ValueError :
109
107
logmessage = 'Database view has changed.'
110
108
logger .critical (logmessage )
111
109
exit ()
112
110
if not netid : # Some people records do not contain netid. Look in SD file. If not there, log and discard person.
113
- print 'missing netid for ' + duid + ' ' + forename + ' ' + surname
114
- for person in sd_dict_list : # Look through SD records
115
- if duid == person ['duid' ]: # If DUID matches...
116
- print person
117
- netid = person ['netid' ] # Assign SD netid to person
118
- logmessage = "Found FDR person %s missing netid." % (duid )
119
- logger .info (logmessage )
120
- print logmessage
121
- break
122
- else : # If also no netid in SD, log and set flag to drop this record.
123
- logmessage = "Person %s missing netid in FDR and SD." % (duid )
124
- logger .critical (logmessage )
125
- print logmessage
126
- drop_record = True
111
+ logmessage = 'Record dropped - No NetID in FDR. %s %s, %s' % (forename , surname , duid )
112
+ logger .critical (logmessage )
113
+ print logmessage
114
+ drop_record = True
115
+ continue
116
+ else :
117
+ pass
118
+
119
+ # for person in sd_dict_list: # Look through SD records
120
+ # if duid == person['duid']: # If DUID matches...
121
+ # print person
122
+ # netid = person['netid'] # Assign SD netid to person
123
+ # logmessage = "Found FDR person %s missing netid." % (duid)
124
+ # logger.info(logmessage)
125
+ # print logmessage
126
+ # break
127
+ # else: # If also no netid in SD, log and set flag to drop this record.
128
+ # logmessage = "Person %s missing netid in FDR and SD." % (duid)
129
+ # logger.critical(logmessage)
130
+ # print logmessage
131
+ # drop_record = True
132
+
127
133
if surname : # If professional name set, use that. Otherwise fall back to legal name.
128
134
fdr_dict ['surname' ] = surname
129
135
fdr_dict ['forename' ] = forename
130
136
if middlename : # Many records do not contain middle name.
131
137
fdr_dict ['middlename' ] = middlename
132
- else : # Legal name block.
138
+ else : # Legal name block
133
139
fdr_dict ['surname' ] = lsurname
134
140
fdr_dict ['forename' ] = lforename
135
141
if lmiddlename :
@@ -142,9 +148,8 @@ def buildFdrDict(data, rpcserver, sd_dict_list):
142
148
email = person ['email' ] # Assign SD netid to person
143
149
logmessage = "FDR person %s missing email found in Service Directory." % (duid )
144
150
missing_email_found_sd += 1
145
- print logmessage
151
+ # print logmessage
146
152
#logger.info(logmessage)
147
- print logmessage
148
153
break
149
154
else :
150
155
email = person ['email' ]
@@ -171,7 +176,7 @@ def buildFdrDict(data, rpcserver, sd_dict_list):
171
176
fdr_dict ['academic' ] = 'Y'
172
177
fdr_dict ['login' ] = 'Y'
173
178
fdr_dict ['authority' ] = 'Shibboleth'
174
- duid_list .append (duid )
179
+ netid_list .append (netid )
175
180
if not drop_record :
176
181
fdr_dict_list .append (fdr_dict )
177
182
else : # Discard this record and log.
@@ -181,7 +186,7 @@ def buildFdrDict(data, rpcserver, sd_dict_list):
181
186
logmessage = '%s FDR records without email addresses' % (missing_fdr_email )
182
187
logger .info (logmessage )
183
188
print '%s people missing FDR email found in SD' % (missing_email_found_sd )
184
- return fdr_dict_list , duid_list
189
+ return fdr_dict_list , netid_list
185
190
186
191
187
192
# Build list of dictionaries of service directory entries after deduplicating people from FDR
@@ -190,39 +195,41 @@ def buildSdDict(sd_file):
190
195
duplicates = 0
191
196
sd_missing_email = 0
192
197
sd = open (sd_file , 'r' )
198
+ print '1'
193
199
for line in sd :
194
200
sd_dict = {}
195
201
duid , netid , surname , forename , email , status = line .split ('|' )
196
- sd_dict [u 'duid' ] = duid
197
- sd_dict [u 'netid' ] = netid
198
- sd_dict [u 'surname' ] = surname
199
- sd_dict [u 'forename' ] = forename
200
- sd_dict [u 'primary' ] = status .strip () # Remove line break
201
- sd_dict [u 'academic' ] = u 'N'
202
- sd_dict [u 'login' ] = u 'Y'
203
- sd_dict [u 'authority' ] = u 'Shibboleth'
202
+ sd_dict ['duid' ] = duid
203
+ sd_dict ['netid' ] = netid
204
+ sd_dict ['surname' ] = surname
205
+ sd_dict ['forename' ] = forename
206
+ sd_dict ['primary' ] = status .strip () # Remove line break
207
+ sd_dict ['academic' ] = 'N'
208
+ sd_dict ['login' ] = 'Y'
209
+ sd_dict ['authority' ] = 'Shibboleth'
204
210
if email :
205
211
email = email .translate (None , "<>" ) # Remove angle brackets present in some email fields
206
- sd_dict [u 'email' ] = email
212
+ sd_dict ['email' ] = email
207
213
else :
208
- sd_dict [u 'email' ] = netid + u '@duke.edu'
214
+ sd_dict ['email' ] = netid + '@duke.edu'
209
215
sd_missing_email += 1
210
216
sd_dict_list .append (sd_dict )
211
217
sd .close ()
212
- logmessage = u 'Found %s Service Directory records.' % (len (sd_dict_list ) + duplicates )
218
+ logmessage = 'Found %s Service Directory records.' % (len (sd_dict_list ) + duplicates )
213
219
logger .info (logmessage )
214
- logmessage = u '%s Service Directory records without email addresses' % (sd_missing_email )
220
+ logmessage = '%s Service Directory records without email addresses' % (sd_missing_email )
215
221
logger .info (logmessage )
216
222
#logmessage = '%s Service Directory records were duplicates.' % (duplicates)
217
223
#logger.info(logmessage)
224
+ print 'testing" return buildDdDict'
218
225
return sd_dict_list
219
226
220
227
# Deduplicate the SD people to prevent creating multiple accounts as some will appear in FDR data.
221
- def dedupeSdDictList (sd_dict_list , duid_list ):
228
+ def dedupeSdDictList (sd_dict_list , netid_list ):
222
229
duplicates = 0
223
230
sd_dict_list_dedupe = []
224
231
for record in sd_dict_list :
225
- if record ['duid ' ] not in duid_list : # Deduplicate these records against FDR records.
232
+ if record ['netid ' ] not in netid_list : # Deduplicate these records against FDR records.
226
233
sd_dict_list_dedupe .append (record )
227
234
duplicates += 1
228
235
logmessage = "Found %s Service record duplicates." % (duplicates )
@@ -235,14 +242,13 @@ def getUniqueAffiliations(fdr_dict_list):
235
242
unique_affiliations_list = []
236
243
for dict in fdr_dict_list :
237
244
if 'secondary' in dict :
238
- for affiliation in dict [u 'secondary' ]:
245
+ for affiliation in dict ['secondary' ]:
239
246
if affiliation not in unique_affiliations_list :
240
247
unique_affiliations_list .append (affiliation )
241
248
return unique_affiliations_list
242
249
243
250
244
251
245
-
246
252
if __name__ == '__main__' :
247
253
try :
248
254
logmessage = "Starting update." # Begin logging
@@ -254,38 +260,36 @@ def getUniqueAffiliations(fdr_dict_list):
254
260
logmessage = 'Database connection error.'
255
261
logger .critical (logmessage )
256
262
exit ()
257
- sql = 'select DUID, NETID, SALUTATION, SURNAME, FIRSTNAME, MIDDLENAME, LEGAL_SURNAME, LEGAL_FIRSTNAME, LEGAL_MIDDLENAME, EMAIL, PRIMARY_VIVO_ORG, PRIMARY_SCHOOL, affiliations from APT.V_PEOPLE_WITH_AFFILIATIONS'
263
+ sql = 'select DUID, NETID, SALUTATION, SURNAME, FIRSTNAME, MIDDLENAME, LEGAL_SURNAME, LEGAL_FIRSTNAME, LEGAL_MIDDLENAME, EMAIL, PRIMARY_VIVO_ORG, PRIMARY_SCHOOL, affiliations, PRIMARY_AFFILIATION from APT.V_PEOPLE_WITH_AFFILIATIONS'
258
264
data = getResults (ora , sql ) # Query FDR. data is a list of tuples, 1 tuple per record.
259
265
logmessage = 'Found %s FDR faculty.' % (len (data ))
260
266
logger .info (logmessage )
261
267
ora .close ()
262
- print '1'
263
268
xml_preabmle = '<?xml version="1.0" encoding="UTF-8" ?>\n <HR_Data>\n ' # Begin the XML string to write to people.xml
264
269
xml_preabmle += '\t <Feed_ID>FDR</Feed_ID>\n '
265
270
xml_preabmle += '\t <people>\n '
266
- print '2'
267
- rpcserver = getServerProxy () # Open connection to Service Directory
271
+ if useldapforemail :
272
+ rpcserver = getServerProxy () # Open connection to Service Directory
273
+ else :
274
+ rpcserver = False
268
275
sd_dict_list = buildSdDict (sd_file ) # Build list of attributes about people from Service Directory dump file.
269
- print '3'
270
- fdr_dict_list , duid_list = buildFdrDict ( data , rpcserver , sd_dict_list )
276
+ fdr_dict_list , netid_list = buildFdrDict ( data , rpcserver , sd_dict_list )
277
+
271
278
unique_affiliations_list = getUniqueAffiliations (fdr_dict_list ) # Build list of unique affiliations/appointments for Elements
272
- duid_list .sort ()
273
- sd_dict_list_dedupe = dedupeSdDictList (sd_dict_list , duid_list ) # Deduplicate Service Directory people so we don't name people twice
279
+ netid_list .sort ()
280
+
281
+ sd_dict_list_dedupe = dedupeSdDictList (sd_dict_list , netid_list ) # Deduplicate Service Directory people so we don't name people twice
282
+ # TESTED TO HERE
274
283
sd_xml = buildXml (sd_dict_list_dedupe ) # Build the XML string from SD people
284
+ print 'testing buildXML sd dict'
275
285
fdr_xml = buildXml (fdr_dict_list ) # Build the XML string for FDR people
286
+ print 'testing buildXML fdr dict'
276
287
xml_postamble = '\t </people>\n </HR_Data>'
277
288
xml = xml_preabmle + fdr_xml + sd_xml + xml_postamble # Complete XML string.
278
- print 'here'
279
- print type (xml )
280
- # testing utf-8
281
- with io .open (xmlfile ,'w' , encoding = 'utf8' ) as f :
282
- f .write (xml )
283
- print 'here2'
289
+
290
+ f = open (xmlfile , 'w' ) # Serialize the XML string
291
+ f .write (xml )
284
292
f .close ()
285
- print 'here3'
286
- #f = open(xmlfile, 'w') # Serialize the XML string
287
- #f.write(xml)
288
- #f.close()
289
293
290
294
af = open (affiliationsfile , 'w' ) # Serialize the unique affiliations
291
295
unique_affiliations_list .sort
@@ -295,12 +299,14 @@ def getUniqueAffiliations(fdr_dict_list):
295
299
logmessage = "Update complete."
296
300
print logmessage
297
301
logger .info (logmessage )
298
- except :
302
+
303
+ except Exception as e :
304
+ print (e )
299
305
# successful sending of email necessitated disabling McAfee email rule
300
306
import smtplib
301
307
from email .mime .text import MIMEText
302
- msg = MIMEText ('The HR data serialization script has failed on Elements production .' )
303
- sender = 'elements @duke.edu'
308
+ msg = MIMEText ('The HR data serialization script has failed on lib-symeldata .' )
309
+ sender = 'jjim.tuttle @duke.edu'
304
310
305
311
msg ['Subject' ] = 'HR data failed on Elements development'
306
312
0 commit comments