1717"""Module containing the manager for all extractors configured in cASO."""
1818
1919import datetime
20+ import json
2021import os .path
2122import sys
23+ import warnings
2224
2325import dateutil .parser
2426from dateutil import tz
4345 default = "caso" ,
4446 help = "Tag used to mark a project in Keystone to be extracted by cASO" ,
4547 ),
48+ cfg .StrOpt (
49+ "vo_property" ,
50+ default = "accounting:VO" ,
51+ help = "Property key used to get the VO name from the project properties. " ,
52+ ),
53+ cfg .StrOpt (
54+ "mapping_file" ,
55+ default = "/etc/caso/voms.json" ,
56+ deprecated_group = "extractor" ,
57+ deprecated_for_removal = True ,
58+ deprecated_reason = "This option is marked for removal in the next release. "
59+ "Please see the release notes, and migrate your current configuration "
60+ "to use the project_mapping file as soon as possible." ,
61+ help = "File containing the VO <-> project mapping as used in Keystone-VOMS." ,
62+ ),
4663 cfg .StrOpt (
4764 "extract-to" ,
4865 deprecated_name = "extract_to" ,
@@ -97,6 +114,7 @@ def __init__(self):
97114 self .extractors = extractors
98115 self .last_run_base = os .path .join (CONF .spooldir , "lastrun" )
99116
117+ self ._voms_map = {}
100118 self .keystone = self ._get_keystone_client ()
101119
102120 @property
@@ -145,6 +163,70 @@ def write_lastrun(self, project):
145163 with open (lfile , "w" ) as fd :
146164 fd .write (str (datetime .datetime .now (tz .tzutc ())))
147165
166+ @property
167+ def voms_map (self ):
168+ """Get the VO map."""
169+ if self ._voms_map :
170+ return self ._voms_map
171+
172+ try :
173+ mapping = json .loads (open (CONF .mapping_file ).read ())
174+ except ValueError :
175+ # FIXME(aloga): raise a proper exception here
176+ raise
177+ else :
178+ self ._voms_map = {}
179+ for vo , vomap in six .iteritems (mapping ):
180+ tenant = vomap .get ("tenant" , None )
181+ tenants = vomap .get ("tenants" , [])
182+ if tenant is not None :
183+ warnings .warn (
184+ "Using deprecated 'tenant' mapping, please "
185+ "use 'projects' instead" ,
186+ DeprecationWarning ,
187+ )
188+ if tenants :
189+ warnings .warn (
190+ "Using deprecated 'tenants' mapping, please "
191+ "use 'projects' instead" ,
192+ DeprecationWarning ,
193+ )
194+ tenants .append (tenant )
195+ projects = vomap .get ("projects" , tenants )
196+ if not projects :
197+ LOG .warning (f"No project mapping found for VO { vo } " )
198+ for project in projects :
199+ self ._voms_map [project ] = vo
200+ return self ._voms_map
201+
202+ def get_project_vo (self , project_id ):
203+ """Get the VO where the project should be mapped."""
204+ project = self .keystone .projects .get (project_id )
205+ project .get ()
206+ vo = project .to_dict ().get (CONF .vo_property , None )
207+ if vo is None :
208+ LOG .warning (
209+ f"No mapping could be found for project '{ project_id } ' in the "
210+ "Keystone project metadata, please check cASO documentation."
211+ )
212+ vo = self .voms_map .get (project_id , None )
213+ if vo is None :
214+ LOG .warning (
215+ "No mapping could be found for project "
216+ f"'{ project_id } ', please check mapping file!"
217+ )
218+ else :
219+ LOG .warning (
220+ "Using deprecated mapping file, please check cASO documentation "
221+ "and migrate to Keystone properties as soon as possible."
222+ )
223+ else :
224+ LOG .debug (
225+ f"Found VO mapping ({ vo } ) in Keystone project '{ project_id } ' "
226+ "metadata."
227+ )
228+ return vo
229+
148230 def get_records (self ):
149231 """Get records from given date.
150232
@@ -173,6 +255,8 @@ def get_records(self):
173255 for project in self .projects :
174256 LOG .info (f"Extracting records for project '{ project } '" )
175257
258+ vo = self .get_project_vo (project )
259+
176260 extract_from = CONF .extract_from or self .get_lastrun (project )
177261 if isinstance (extract_from , six .string_types ):
178262 extract_from = dateutil .parser .parse (extract_from )
@@ -196,7 +280,7 @@ def get_records(self):
196280 f"({ extract_from } to { extract_to } )"
197281 )
198282 try :
199- extractor = extractor_cls (project )
283+ extractor = extractor_cls (project , vo )
200284 records = extractor .extract (extract_from , extract_to )
201285 current_count = len (records )
202286 record_count += current_count
0 commit comments