View Javadoc

1   /*
2    * ResourceManager.java
3    *
4    * Created on May 24, 2004, 3:17 PM
5    */
6   
7   package gov.bnl.gums;
8   
9   import gov.bnl.gums.account.*;
10  import gov.bnl.gums.configuration.Configuration;
11  import gov.bnl.gums.groupToAccount.GroupToAccountMapping;
12  import gov.bnl.gums.hostToGroup.HostToGroupMapping;
13  import gov.bnl.gums.userGroup.UserGroup;
14  import gov.bnl.gums.userGroup.VOMSUserGroup;
15  
16  import java.util.*;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  
21  /** 
22   * The main interface of the core logic for GUMS, allows to update the
23   * groups, generate the gridMapfiles and to map a single user.
24   *
25   * @author Gabriele Carcassi, Jay Packard
26   */
27  public class ResourceManager {
28      private Log log = LogFactory.getLog(ResourceManager.class);
29      private Log resourceAdminLog = LogFactory.getLog(GUMS.resourceAdminLog);
30      GUMS gums;
31      
32      /**
33       * Creates a Resource Manager for a particular instance of the GUMS server.
34       * 
35       * @param gums
36       */
37      public ResourceManager(GUMS gums) {
38      	this.gums = gums;
39      }
40      
41      
42      /**
43       * @param hostname
44       * @return
45       */
46      public String generateOsgUserVoMap(String hostname) {
47          Configuration conf = gums.getConfiguration();
48          HostToGroupMapping hostGroup = hostToGroupMapping(conf, hostname);
49          if (hostGroup == null)
50              throw new RuntimeException("The host '" + hostname + "' is not defined in any group.");
51          StringBuffer osgMapBuffer = new StringBuffer("");
52          Iterator iter = hostGroup.getGroupToAccountMappings().iterator();
53          
54          osgMapBuffer.append("#User-VO map\n");
55          osgMapBuffer.append("# #comment line, format of each regular line line: account VO\n");
56          osgMapBuffer.append("# Next 2 lines with VO names, same order, all lowercase, with case (lines starting with #voi, #VOc)\n");
57          
58          String voi = "#voi";
59          String voc = "#VOc";
60          while (iter.hasNext()) {
61              GroupToAccountMapping gMap = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)iter.next() );
62              Collection userGroups = gMap.getUserGroups();
63              Iterator userGroupIt = userGroups.iterator();
64              while (userGroupIt.hasNext()) {
65              	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupIt.next() );
66  	            if (userGroup.getMemberList().size()!=0 && !gMap.getAccountingVoSubgroup().equals("") && !gMap.getAccountingVo().equals("")) {
67  	                voi = voi + " " + gMap.getAccountingVoSubgroup();
68  	                voc = voc + " " + gMap.getAccountingVo();
69  	            }
70              }
71          }
72          
73          osgMapBuffer.append(voi);
74          osgMapBuffer.append("\n");
75          osgMapBuffer.append(voc);
76          osgMapBuffer.append("\n");
77          
78          iter = hostGroup.getGroupToAccountMappings().iterator();
79          
80          List accountsInMap = new ArrayList();
81          int unknownCount = 1;
82          
83          while (iter.hasNext()) {
84              GroupToAccountMapping gMap = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)iter.next() );
85              if (!gMap.getAccountingVoSubgroup().equals("") && !gMap.getAccountingVo().equals("")) {
86  	            Collection userGroups = gMap.getUserGroups();
87              	Collection accountMappers = gMap.getAccountMappers();
88  	            Iterator userGroupIt = userGroups.iterator();
89  	            while (userGroupIt.hasNext()) {
90  	            	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupIt.next() );
91  		            List members = userGroup.getMemberList();
92  		            members = new ArrayList(members);
93  		            osgMapBuffer.append("#---- accounts for vo: " + userGroup.getName() + " ----#\n");          
94  		            /*if (members.size()==0) {
95  	                    Iterator accountMapperIt = accountMappers.iterator();
96  	                    while (accountMapperIt.hasNext()) {
97  	                    	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMapperIt.next() );
98  	                    	String account = null;
99  	                    	if (accountMapper instanceof GroupAccountMapper)
100 	                    		account = ((GroupAccountMapper)accountMapper).getAccountName();
101 	                    	else if (accountMapper instanceof AccountPoolMapper)
102 			                    account = ((AccountPoolMapper)accountMapper).getAccountPool();
103 	                    	if (account == null)
104 	                    		account = "unknown" + Integer.toString(unknownCount++);
105 	                    	if (!accountsInMap.contains(account)) {
106 		                    	osgMapBuffer.append(account);
107 			                    osgMapBuffer.append(' ');
108 			                    osgMapBuffer.append(gMap.getAccountingVoSubgroup());
109 			                    osgMapBuffer.append("\n");
110 			                    accountsInMap.add(account);
111 	                    	}
112 	                    }
113 		            }*/
114 		            Collections.sort(members, retrieveUserComparatorByDN());
115 		            Iterator memberIter = members.iterator();
116 		            while (memberIter.hasNext()) {
117 		                GridUser user = (GridUser) memberIter.next();
118 	                    Iterator accountMapperIt = accountMappers.iterator();
119 	                    while (accountMapperIt.hasNext()) {
120 	                    	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMapperIt.next() );
121 			                String account = accountMapper.mapUser(user.getCertificateDN(), false);
122 			                if ((account != null) && !accountsInMap.contains(account)) {
123 			                	osgMapBuffer.append(account);
124 			                	osgMapBuffer.append(' ');
125 			                	osgMapBuffer.append(gMap.getAccountingVoSubgroup());
126 			                	osgMapBuffer.append("\n");
127 			                    accountsInMap.add(account);
128 			                }
129 	                    }
130 		            }
131 	            }
132             }
133         }
134         String finalOsgMap = osgMapBuffer.toString();
135         return finalOsgMap;
136     }
137     
138 
139     /**
140      * Generates a fqan to account mapping for a given host and prints it to out.
141      * 
142      * @param hostname
143      * @return
144      */
145     public String generateFqanMapfile(String hostname) {
146         String mapfile;
147         mapfile = generateFqanMapfileImpl(hostname);
148         return mapfile;
149     }    
150     
151     /**
152      * Generates a grid mapfile for a given host and prints it to out.
153      * 
154      * @param hostname
155      * @param includeFQAN
156      * @return
157      */
158     public String generateGridMapfile(String hostname, boolean includeFQAN) {
159         String mapfile;
160         mapfile = generateGridMapfileImpl(hostname, includeFQAN);
161         return mapfile;
162     }
163     
164     /**
165      * Maps a user to a local account for a given host to a grid identity.
166      * 
167      * @param hostname
168      * @param user
169      * @return
170      */
171     public String map(String hostname, GridUser user) {
172         String value;
173         value = mapImpl(hostname, user);
174         return value;
175     }
176     
177     /**
178      * Map a local account to a list of grid identity
179      * 
180      * @param accountName
181      * @return
182      */
183     public String mapAccount(String accountName) {
184     	TreeSet dns = new TreeSet();
185         Configuration conf = gums.getConfiguration();
186         Iterator g2AMappingsIt = conf.getGroupToAccountMappings().values().iterator();
187         while (g2AMappingsIt.hasNext()) {
188             GroupToAccountMapping g2AMapping = (GroupToAccountMapping) g2AMappingsIt.next();
189             Collection userGroups = g2AMapping.getUserGroups();
190             Iterator userGroupsIt = userGroups.iterator();
191             while (userGroupsIt.hasNext()) {
192             	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupsIt.next() );
193             	List users = userGroup.getMemberList();
194             	Iterator usersIt = users.iterator();
195             	while (usersIt.hasNext()) {
196             		GridUser user = (GridUser)usersIt.next();
197                 	Collection accountMappers = g2AMapping.getAccountMappers();
198                     Iterator accountMappersIt = accountMappers.iterator();
199                     while (accountMappersIt.hasNext()) {
200                     	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMappersIt.next() );
201                 		if (accountName.equals(accountMapper.mapUser(user.getCertificateDN(), false)) && !dns.contains(user.getCertificateDN()))
202                         	dns.add(user.getCertificateDN());
203                     }            		
204             	}
205             }
206         }
207         
208         StringBuffer output = new StringBuffer();
209         Iterator it = dns.iterator();
210         while(it.hasNext()) {
211         	output.append( (String)it.next() );
212         	output.append("\n");
213         }
214         
215         return output.toString();
216     }
217     
218     /**
219      * Scans the configuration and calls updateMembers() on all the groups,
220      * updating the local database.
221      */
222     public void updateGroups() {
223         updateGroupsImpl();
224     }
225     
226     /**
227      * @param hostname
228      * @return
229      */
230     private String generateFqanMapfile(HostToGroupMapping hToGMapping) {   
231        	Configuration conf = hToGMapping.getConfiguration();
232         Iterator iter = hToGMapping.getGroupToAccountMappings().iterator();
233         TreeSet usersInMap = new TreeSet();
234         
235         StringBuffer fqanMapfileBuffer = new StringBuffer("");
236         while (iter.hasNext()) {
237             GroupToAccountMapping gMap = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)iter.next() );
238             Collection userGroups = gMap.getUserGroups();
239             Iterator userGroupIt = userGroups.iterator();
240             while (userGroupIt.hasNext()) {
241             	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupIt.next() );
242             	if (userGroup instanceof VOMSUserGroup) {
243             		VOMSUserGroup vomsUserGroup = (VOMSUserGroup)userGroup;
244             		Collection accountMappers = gMap.getAccountMappers();
245                     Iterator accountMapperIt = accountMappers.iterator();
246                     while (accountMapperIt.hasNext()) {
247                     	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMapperIt.next() );
248                     	if (accountMapper instanceof GroupAccountMapper || accountMapper instanceof AccountPoolMapper) {
249 	                		String fqan = vomsUserGroup.getVoGroup() + "/" + vomsUserGroup.getRole();
250                         	String account = null;
251 	                       	if (accountMapper instanceof GroupAccountMapper) {
252 	                    		GroupAccountMapper groupPoolMapper = (GroupAccountMapper)accountMapper;
253 	                    		account = groupPoolMapper.getAccountName();
254 	                    	}
255 	                    	else if (accountMapper instanceof AccountPoolMapper){
256 	                    		AccountPoolMapper accountPoolMapper = (AccountPoolMapper)accountMapper;
257 	                    		account = accountPoolMapper.getAssignments();
258 	                    		if (account==null || account.length()==0)
259 	                    			account = "null";
260 	                    	}
261 	                       	if (account != null) {
262 	                       		fqanMapfileBuffer.append('"');
263 	                       		fqanMapfileBuffer.append( fqan );
264 	                       		fqanMapfileBuffer.append('"');
265 	                       		fqanMapfileBuffer.append(' ');
266 	                       		fqanMapfileBuffer.append( account );
267 	                       		fqanMapfileBuffer.append("\n");
268 	                       		break;
269 	                       	}
270                     	}
271                     }
272             	}
273             }
274         }
275         
276         return fqanMapfileBuffer.toString();
277     }    
278     
279     private String generateGridMapfile(HostToGroupMapping hToGMapping, boolean includeFQAN) {
280     	Configuration conf = hToGMapping.getConfiguration();
281         Iterator iter = hToGMapping.getGroupToAccountMappings().iterator();
282         TreeSet usersInMap = new TreeSet();
283         
284         StringBuffer gridMapfileBuffer = new StringBuffer("");
285         while (iter.hasNext()) {
286             GroupToAccountMapping gMap = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)iter.next() );
287             Collection userGroups = gMap.getUserGroups();
288             Iterator userGroupIt = userGroups.iterator();
289             while (userGroupIt.hasNext()) {
290             	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupIt.next() );
291 	            List members = userGroup.getMemberList();
292 	            members = new ArrayList(members);
293 	            Collections.sort(members, retrieveUserComparatorByDN());
294 	            gridMapfileBuffer.append("#---- members of vo: " + userGroup.getName() + " ----#\n");
295 	            Iterator memberIter = members.iterator();
296 	            if (includeFQAN) {
297 		            while (memberIter.hasNext()) {
298 		                GridUser user = (GridUser) memberIter.next();
299 	                    String fqan = user.getVoFQAN()!=null?user.getVoFQAN().toString():"";
300 		                if ( !usersInMap.contains(user.getCertificateDN() + fqan) ) {
301 		                	Collection accountMappers = gMap.getAccountMappers();
302 		                    Iterator accountMappersIt = accountMappers.iterator();
303 		                    while (accountMappersIt.hasNext()) {
304 		                    	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMappersIt.next() );
305 			                	String account = accountMapper.mapUser(user.getCertificateDN(), true);
306 			                	if (account != null) {
307 			                        gridMapfileBuffer.append('"');
308 			                        gridMapfileBuffer.append( user.getCertificateDN() );
309 			                        gridMapfileBuffer.append('"' );
310 			                        gridMapfileBuffer.append(" \"");
311 			                        gridMapfileBuffer.append( fqan );
312 			                        gridMapfileBuffer.append('"');         	
313 			                        gridMapfileBuffer.append(' ');
314 			                        gridMapfileBuffer.append( account );
315 			                        gridMapfileBuffer.append("\n");
316 		                        	usersInMap.add( user.getCertificateDN() + fqan );
317 		                        	break;
318 			                    } else {
319 			                        resourceAdminLog.warn("User " + user + " from group " + gMap.getUserGroups() + " can't be mapped.");
320 			                    }
321 		                    }
322 		            	}
323 		            }
324 	            }
325 	            else {
326 		            while (memberIter.hasNext()) {
327 		                GridUser user = (GridUser) memberIter.next();
328 		                if (!usersInMap.contains(user.getCertificateDN()) && userGroup.isInGroup(new GridUser(user.getCertificateDN(), null))) {
329 		                	Collection accountMappers = gMap.getAccountMappers();
330 		                    Iterator accountMappersIt = accountMappers.iterator();
331 		                    while (accountMappersIt.hasNext()) {
332 		                    	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMappersIt.next() );
333 			                	String account = accountMapper.mapUser(user.getCertificateDN(), true);
334 			                    if (account != null) {
335 			                        gridMapfileBuffer.append('"');
336 			                        gridMapfileBuffer.append( user.getCertificateDN() );
337 			                        gridMapfileBuffer.append('"' );
338 			                        gridMapfileBuffer.append(' ');
339 			                        gridMapfileBuffer.append( account );
340 			                        gridMapfileBuffer.append("\n");
341 		                        	usersInMap.add(user.getCertificateDN());
342 		                        	break;
343 			                    } else {
344 			                        resourceAdminLog.warn("User " + user + " from group " + gMap.getUserGroups() + " can't be mapped.");
345 			                    }
346 		                    }
347 		            	}
348 		            }	            	
349 	            }
350             }
351         }
352 
353         String finalGridmapfile = gridMapfileBuffer.toString();
354         return finalGridmapfile;
355     }
356  
357     private String generateFqanMapfileImpl(String hostname) {
358         Configuration conf = gums.getConfiguration();
359         HostToGroupMapping host2GroupMapper = hostToGroupMapping(conf, hostname);
360         if (host2GroupMapper == null) return null;
361         String mapfile = generateFqanMapfile(host2GroupMapper);
362         return mapfile;
363     }
364     
365     private String generateGridMapfileImpl(String hostname, boolean includeFqan) {
366         Configuration conf = gums.getConfiguration();
367         HostToGroupMapping host2GroupMapper = hostToGroupMapping(conf, hostname);
368         if (host2GroupMapper == null) return null;
369         String mapfile = generateGridMapfile(host2GroupMapper, includeFqan);
370         return mapfile;
371     }
372     
373     private HostToGroupMapping hostToGroupMapping(Configuration conf, String hostname) {
374     	Collection hostToGroupMappers = conf.getHostToGroupMappings();
375     	Iterator it = hostToGroupMappers.iterator();
376         while (it.hasNext()) {
377             HostToGroupMapping hostToGroupMapper = (HostToGroupMapping) it.next();
378             if (hostToGroupMapper.isInGroup(hostname)) {
379                 return hostToGroupMapper;
380             }
381         }
382         return null;
383     }
384 
385     private String mapImpl(String hostname, GridUser user) {
386         Configuration conf = gums.getConfiguration();
387         HostToGroupMapping hostToGroupMapping = hostToGroupMapping(conf, hostname);
388         if (hostToGroupMapping == null) return null;
389         Iterator g2AMappingsIt = hostToGroupMapping.getGroupToAccountMappings().iterator();
390         while (g2AMappingsIt.hasNext()) {
391             GroupToAccountMapping g2AMapping = (GroupToAccountMapping) conf.getGroupToAccountMapping( (String)g2AMappingsIt.next() );
392             Collection userGroups = g2AMapping.getUserGroups();
393             Iterator userGroupsIt = userGroups.iterator();
394             while (userGroupsIt.hasNext()) {
395             	UserGroup userGroup = (UserGroup) conf.getUserGroup( (String)userGroupsIt.next() );
396                 if (userGroup.isInGroup(user)) {
397                 	Collection accountMappers = g2AMapping.getAccountMappers();
398                     Iterator accountMappersIt = accountMappers.iterator();
399                     while (accountMappersIt.hasNext()) {
400                     	AccountMapper accountMapper = (AccountMapper) conf.getAccountMapper( (String)accountMappersIt.next() );
401                         String localUser = accountMapper.mapUser(user.getCertificateDN(), true);
402                         if (localUser != null) {
403                             return localUser;
404                         } else {
405                             if (conf.isErrorOnMissedMapping()) {
406                                 resourceAdminLog.error("User " + user + " wasn't mapped even though is present in group " + g2AMapping.getUserGroups());
407                             }
408                         }
409                     }
410                 }
411             }
412         }
413         return null;
414     }
415 
416     private Comparator retrieveUserComparatorByDN() {
417         return new Comparator() {
418             public int compare(Object o1, Object o2) {
419                 GridUser user1 = (GridUser) o1;
420                 GridUser user2 = (GridUser) o2;
421                 return user1.compareDn(user2);
422             }
423         };
424     }
425     
426     private void updateGroupsImpl() {
427         boolean success = true;
428         Collection groups = gums.getConfiguration().getUserGroups().values();
429         log.info("Updating group information for all " + groups.size() + " groups");
430         Iterator iter = groups.iterator();
431         while (iter.hasNext()) {
432             UserGroup group = (UserGroup) iter.next();
433             log.debug("Updating group " + group);
434             try {
435                 group.updateMembers();
436                 resourceAdminLog.info(group.toString() + " updated");
437             } catch (Exception e) {
438                 resourceAdminLog.warn(group.toString() + " wasn't updated successfully: " + " [" + e.getMessage() + "]");
439                 log.warn("updateMember for " + group + " threw an exception", e);
440                 success = false;
441             }
442         }
443         if (!success) {
444             throw new RuntimeException("Some groups weren't updated correctly: consult the logs for more details. Check GUMS configuration or the status of the VO servers.");
445         }
446     }
447 }