ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/CRAB/python/BdiiLdap.py
Revision: 1.1
Committed: Thu Jul 31 19:51:23 2008 UTC (16 years, 9 months ago) by ewv
Content type: text/x-python
Branch: MAIN
CVS Tags: CRAB_2_3_2_pre2
Log Message:
New BDII code that uses ldap library, fallback to CLI

File Contents

# User Rev Content
1 ewv 1.1 #!/usr/bin/env python
2     import re, sys
3     import ldap
4    
5     DEBUG = 0
6     ce_to_cluster_map = {}
7     cluster_to_site_map = {}
8    
9     def runldapquery(filter, attribute, bdii):
10     if DEBUG:
11     print "runldapquery ["+bdii+"]", filter[0:100], attribute[0:100]
12     attribute = attribute.split(' ')
13     filter = filter.strip()
14     filter = filter.lstrip("'").rstrip("'")
15    
16     bdiiuri = 'ldap://' + bdii + ':2170'
17     l = ldap.initialize(bdiiuri)
18    
19     l.simple_bind_s('', '')
20    
21     base = "o=grid"
22     scope = ldap.SCOPE_SUBTREE
23     timeout = 0
24     result_set = []
25     filter = filter.strip("'")
26    
27     try:
28     result_id = l.search(base, scope, filter, attribute)
29     while 1:
30     result_type, result_data = l.result(result_id, timeout)
31     if (result_data == []):
32     break
33     else:
34     if result_type == ldap.RES_SEARCH_ENTRY:
35     result_set.append(result_data)
36    
37     except ldap.LDAPError, error_message:
38     print error_message
39    
40     return result_set
41    
42     def getJMListFromSEList(selist, bdii='exp-bdii.cern.ch'):
43     """
44     Given a list of SE FQDNs, return list of CEUniqueIDs that advertise CMS
45     support and are in Production,
46     sorted by number of waiting jobs in descending order
47     """
48     jmlist = []
49    
50     query = buildOrQuery('GlueCESEBindGroupSEUniqueID', selist)
51     pout = runldapquery(query, 'GlueCESEBindGroupCEUniqueID', bdii)
52    
53     query = "(&(GlueCEAccessControlBaseRule=VO:cms)(GlueCEStateStatus=Production)"
54     query += buildOrQuery('GlueCEUniqueID', [l[0][1]['GlueCESEBindGroupCEUniqueID'][0] for l in pout])
55     query += ")"
56     pout = runldapquery(query, 'GlueCEUniqueID GlueCEStateWaitingJobs', bdii)
57    
58     jminfo_list = []
59     for x in pout:
60     jminfo = {}
61     ce = x[0][1]['GlueCEUniqueID'][0]
62     waiting_jobs = x[0][1]['GlueCEStateWaitingJobs'][0]
63    
64     jminfo['ce'] = ce
65     jminfo['waiting_jobs'] = waiting_jobs
66     jminfo_list.append(jminfo)
67    
68     def compare_by (fieldname):
69     """ Comparison function for sorting dicts """
70     def compare_two_dicts (a, b):
71     return cmp(int(a[fieldname]), int(b[fieldname]))
72     return compare_two_dicts
73    
74     jminfo_list.sort(compare_by('waiting_jobs'))
75     jmlist = [x['ce'] for x in jminfo_list]
76    
77     return jmlist
78    
79     def generateMaps(ce_list, bdii='exp-bdii.cern.ch'):
80     """
81     Generate maps of CE to Cluster and Cluster to Site as the globals
82     ce_to_cluster_map, cluster_to_site_map
83    
84     ce_list: list of GlueCEUniqueIDs
85     bdii: BDII instance to query
86     """
87     # if ce_to_cluster_map: return
88     query = buildOrQuery('GlueCEUniqueID', ce_list)
89    
90     pout = runldapquery(query, 'GlueCEUniqueID GlueForeignKey', bdii)
91    
92     r = re.compile('^GlueClusterUniqueID\s*=\s*(.*)')
93     for x in pout:
94     host = x[0][1]['GlueCEUniqueID'][0]
95     clusterid = x[0][1]['GlueForeignKey'][0]
96     m = r.match(clusterid)
97     if m: ce_to_cluster_map[host] = m.groups()[0]
98    
99     query = "(&(objectClass=GlueCluster)"
100     query += buildOrQuery('GlueClusterUniqueID', ce_to_cluster_map.values())
101     query += ")"
102    
103     pout = runldapquery(query, 'GlueClusterUniqueID GlueForeignKey', bdii)
104     r = re.compile('^GlueSiteUniqueID=(.*)')
105     for x in pout:
106     cluster = x[0][1]['GlueClusterUniqueID'][0]
107     foreign_keys = x[0][1]['GlueForeignKey']
108     for foreign_key in foreign_keys:
109     m = r.match(foreign_key)
110     if m:
111     site = m.groups()[0]
112     cluster_to_site_map[cluster] = site
113    
114     def buildOrQuery(gluekey, list):
115     """
116     Returns a nugget of LDAP requesting the OR of all items
117     of the list equal to the gluekey
118     """
119    
120     query = "(|"
121     for x in list:
122     query += "(%s=%s)" % (gluekey, x)
123     query += ")"
124     return query
125    
126     def isOSGSite(host_list, bdii='exp-bdii.cern.ch'):
127     """
128     Given a list of CEs, return only the ones which belong to OSG sites
129     """
130     if (not ce_to_cluster_map): generateMaps(host_list, bdii)
131    
132     query = buildOrQuery('GlueSiteUniqueID', cluster_to_site_map.values())
133     pout = runldapquery(query, 'GlueSiteUniqueID GlueSiteDescription', bdii)
134     osg_site_list = []
135     for x in pout:
136     site_descr = x[0][1]['GlueSiteDescription'][0]
137    
138     if (site_descr.find('OSG') != -1):
139     osg_site_list.append(x[0][1]['GlueSiteUniqueID'][0])
140    
141     osg_host_list = []
142    
143     for host in host_list:
144     cluster = ce_to_cluster_map[host]
145     site = cluster_to_site_map[cluster]
146    
147     if (osg_site_list.count(site)):
148     osg_host_list.append(host)
149    
150     return osg_host_list
151    
152     def getSoftwareAndArch(host_list, software, arch, bdii='exp-bdii.cern.ch'):
153     """
154     Given a list of CEs, return only those that match a given software
155     and architecture tag
156     """
157     if (not ce_to_cluster_map): generateMaps(host_list, bdii)
158    
159     results_list = []
160     software = 'VO-cms-' + software
161     arch = 'VO-cms-' + arch
162     query = "'(&(GlueHostApplicationSoftwareRunTimeEnvironment="+software+ ")"
163     query += "(GlueHostApplicationSoftwareRunTimeEnvironment="+arch+")"
164    
165     query += buildOrQuery('GlueChunkKey=GlueClusterUniqueID', [ce_to_cluster_map[h] for h in host_list])
166     query += ")"
167    
168     pout = runldapquery(query, 'GlueHostApplicationSoftwareRunTimeEnvironment GlueChunkKey', bdii)
169     clusterlist = [x[0][1]['GlueChunkKey'][0] for x in pout]
170    
171     results_list = []
172     for jm in host_list:
173     cluster = "GlueClusterUniqueID=" + ce_to_cluster_map[jm]
174     if (clusterlist.count(cluster) != 0):
175     results_list.append(jm)
176    
177     return results_list
178    
179    
180     def getJobManagerList(selist, software, arch, bdii='exp-bdii.cern.ch', onlyOSG=True):
181     """
182     Given a list of SE FQDNs, return list of CEUniqueIDs that advertise CMS
183     support and are in Production, sorted by number of waiting jobs in
184     descending order that have a given software and arch.
185    
186     If OnlyOSG is True, return only OSG Sites.
187     """
188    
189     jmlist = getJMListFromSEList(selist, bdii)
190     generateMaps(jmlist, bdii)
191     if (onlyOSG): jmlist = isOSGSite(jmlist, bdii)
192     jmlist = getSoftwareAndArch(jmlist, software, arch, bdii)
193     res = removeQueues(jmlist)
194     return res
195    
196     def removeQueues(celist):
197     """
198     Given a list of CEUniqueIDs, return a list of jobmanager contact
199     strings.
200     """
201     r = re.compile('^(.*:.*/jobmanager-.*?)-(.*)')
202     jmlist = []
203     for x in celist:
204     m = r.match(x)
205     if m:
206     item = m.groups()[0]
207     if (jmlist.count(item) == 0):
208     jmlist.append(item)
209     return jmlist
210    
211     def listAllCEs(bdii='exp-bdii.cern.ch'):
212     ''' List all GlueCEUniqueIDs that advertise support for CMS '''
213    
214     RE_cename = re.compile('^GlueCEUniqueID: (.*)', re.IGNORECASE)
215     filt = "'(&(GlueCEUniqueID=*)(GlueCEAccessControlBaseRule=VO:cms))'"
216     res = runldapquery(filt, 'GlueCEUniqueID', bdii)
217     ceList = [x[0][1]['GlueCEUniqueID'][0] for x in res]
218     return ceList
219    
220     def listAllSEs(bdii='exp-bdii.cern.ch'):
221     ''' List all SEs that are bound to CEs that advertise support for CMS '''
222    
223     RE_sename = re.compile('^GlueCESEBindGroupSEUniqueID: (.*)', re.IGNORECASE)
224     seList = []
225     ceList = listAllCEs(bdii)
226    
227     query = buildOrQuery('GlueCESEBindGroupCEUniqueID', ceList)
228     res = runldapquery(query, 'GlueCESEBindGroupSEUniqueID', bdii)
229    
230     for x in res:
231     try:
232     item = x[0][1]['GlueCESEBindGroupSEUniqueID'][0]
233     except KeyError:
234     # Sometimes we publish a CESE BindGroup without an SE attached
235     pass
236    
237     if (seList.count(item) == 0): seList.append(item)
238     return seList