Reconciliations can be run in ITIM directly (Service / Reconcile Now), or by setting a reconciliation schedule. In the latter case, when you have dozens or hundreds of services, it can become quite boring to create a reconcilisation schedule for each service.
We can run a reconciliation in batch mode, with 2 options:
- directly thru Java API (ITIM extensions)
- using Python - Jython in fact - APIScript (http://www-01.ibm.com/software/brandcatalog/portal/opal/details?NavCode=...)
We were using this for several monthes, but were having troubles with entries which were not reconciliated in batch mode. If we ran reconciliation on the service with the same filter, then the reconciliation was OK.
After a day of investigating, I discover that in order to run successfully reconciliations, you must go thru several steps :
- Search serviceMO
- Set a Reconciliation Unit Data for this Service
- Retrieve Reconciliation Unit for this Service (*)
- Run a reconciliation, based on this Reconciliation Unit Data
- Optionally remove the temporary Reconciliation Unit Data (this is because we want to avoir the reconciliation to be schedule internally by ITIM).
(*) : if you don't call the recon_mgr.getReconUnits(my_service) after setting the new schedule, the reconciliation still fails.
Example in Java
In java, you will use several objects :
- ServiceMO : Service managed object for our service
- ReconManager : the class used to manage reconciliations
- ReconUnitData : definition of a Reconciliation Schedule
You can refer to the attache RunRecon.java file which is linked to this article. In short, you will have
Search default platform and subject // Create a new reconciliation manager ReconManager reconManager = new ReconManager(platform, subject); // Create a new reconciliation unit data ReconUnitData newReconUnitData = new ReconUnitData(); // Create the Service MO ServiceMO serviceMO = new ServiceMO(platform, subject, service.getDistinguishedName()); // Add a (temporary) reconciliation unit reconManager.addReconUnitData(serviceMO, newReconUnitData, null); // Retrieve reconciliations for this service Collection reconDataCollection = reconManager.getReconUnits(serviceMO); // run reconciliation request = reconManager.runRecon(serviceMO, reconData); // remove reconciliation reconManager.removeReconUnitData(serviceMO, reconData);
Example with Python APIscript
I have been testing the reconciliation process with APIscript, which is a quick way to run API. Here is the script, I tried to put some intersting comments.
# Run a reconciliation on a specific service # import apiscript.util import jarray import time from java.util import ArrayList from java.util import Collections from com.ibm.itim.apps.recon import ReconManager,ReconUnitData ## Get default platform context and subject (platform_ctx, subject) = apiscript.util.get_default_platform_ctx_and_subject() ## Create a Reconciliation Manager recon_mgr = ReconManager(platform_ctx, subject) # delay between runRecon and removeReconUnitData in seconds (just in case) time_to_wait=2 # set reconciliation information batch_ID=127 recon_unit_data = ReconUnitData() ## Do NOT lock service during reconciliation recon_unit_data.setLockService(java.lang.Boolean(java.lang.Boolean.FALSE)) ## Set maximum duration to 360 minutes (6 hours) recon_unit_data.setMaxDuration(java.lang.Integer(360).longValue()) recon_unit_data.setMonth(0) ## Weekly reconciliation on Friday recon_unit_data.setDayOfWeek(5) recon_unit_data.setMinute(30) ## This is the filter we use for Active Directory, Oracle profile recon_unit_data.setReconQueryFilter("(ERUID=*)") recon_unit_data.setID(batch_ID) # Main OU for service ## Set this accordingly to your setup main_ou="MY-ORGANIZATION" my_org_collection = apiscript.util.orgchart.get_containers_by_attr("ou", main_ou) my_ou = my_org_collection.toArray() if len(sys.argv) != 1: print "Usage: recon_now ServiceName " sys.exit(-1) ## Service name is entered as argument of the program my_service = sys.argv # Create a serviceMgr and retrieve Services servicemgr=apiscript.util.service.get_default_service_mgr() services = servicemgr.getServices(my_ou,service_Profile,my_service) for my_service in services: service_do = my_service.getData() print "--- Service name is: %s" % service_do.name ## ReconUnitData.name is mandatory recon_unit_data.setName(service_do.name) recon_collection = ArrayList() recon_collection.add(recon_unit_data) print "--- Set temporary reconciliation Unit Data on service %s" % service_do.name recon_mgr.setReconUnits(my_service, recon_collection) ## we could also us addReconUnitData # List recon schedules print "--- Retrieve Recon Schedules" recon_collection=recon_mgr.getReconUnits(my_service) for myrecon in recon_collection: print "---" recon_id = myrecon.getID() if recon_id == batch_ID: print "--- Run reconciliation" request = recon_mgr.runRecon(my_service, myrecon) print "--- Reconciliation request ID is %s" % request.ID time.sleep(time_to_wait) print "--- Delete temporary reconciliation schedule" recon_mgr.removeReconUnitData(my_service, myrecon) print "--- End of program"
Then, to run this script, I am running, for example for service AD-001 (Active Directory) :
bin/apiscript.ksh -f recon_now.py AD-001