Yair Zaslavsky has uploaded a new change for review. Change subject: aaa: Fixing Sync ......................................................................
aaa: Fixing Sync Change-Id: I3a66a7c235f16ff26cac3a779de688c73d67f4a2 Topic: AAA Signed-off-by: Yair Zaslavsky <yzasl...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DbUserCacheManager.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DirectoryEntryKey.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SyncUsers.java 3 files changed, 145 insertions(+), 207 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/15/29915/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DbUserCacheManager.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DbUserCacheManager.java index b348104..83f89ee 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DbUserCacheManager.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DbUserCacheManager.java @@ -1,29 +1,13 @@ package org.ovirt.engine.core.bll; -import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang.StringUtils; -import org.ovirt.engine.core.aaa.AuthzUtils; -import org.ovirt.engine.core.aaa.DirectoryGroup; -import org.ovirt.engine.core.aaa.DirectoryUser; -import org.ovirt.engine.core.aaa.DirectoryUtils; import org.ovirt.engine.core.common.businessentities.DbGroup; -import org.ovirt.engine.core.common.businessentities.DbUser; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; -import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.DbFacade; -import org.ovirt.engine.core.dao.DbGroupDAO; -import org.ovirt.engine.core.dao.DbUserDAO; -import org.ovirt.engine.core.extensions.mgr.ExtensionProxy; -import org.ovirt.engine.core.utils.collections.MultiValueMapUtils; -import org.ovirt.engine.core.utils.extensionsmgr.EngineExtensionsManager; import org.ovirt.engine.core.utils.log.Log; import org.ovirt.engine.core.utils.log.LogFactory; import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation; @@ -68,197 +52,7 @@ */ @OnTimerMethodAnnotation("refreshAllUsers") public void refreshAllUsers() { - // We will need the DAO: - DbUserDAO dao = DbFacade.getInstance().getDbUserDao(); - - // Retrieve all the users from the database: - List<DbUser> dbUsers = dao.getAll(); - List<DbGroup> dbGroups = DbFacade.getInstance().getDbGroupDao().getAll(); - for (DbGroup group : dbGroups) { - groupsMap.put(group.getExternalId(), group); - } - - // Classify the users by directory. Note that the resulting map may have an entry with a null key, that - // corresponds to the users whose directory has been removed from the configuration. - Map<String, List<DbUser>> authzToPrincipalMap = new HashMap<>(); - Map<String, ExtensionProxy> authzMap = new HashMap<>(); - - for (DbUser dbUser : dbUsers) { - ExtensionProxy authz = EngineExtensionsManager.getInstance().getExtensionByName(dbUser.getDomain()); - if (authz == null) { - log.warn(String.format("No authz extension was found for user %1$s. It is possible that the relevant " + - "domain for the user was removed for the user. Marking the user as inactive", - dbUser.getLoginName())); - if (dbUser.isActive()) { - dbUser.setActive(false); - dao.update(dbUser); - } - continue; - - } - String auhtzName = AuthzUtils.getName(authz); - MultiValueMapUtils.addToMap(auhtzName, dbUser, authzToPrincipalMap); - authzMap.put(auhtzName, authz); - } - - // Refresh the users for each directory: - List<DbUser> updates = new ArrayList<>(); - for (Map.Entry<String, List<DbUser>> entry : authzToPrincipalMap.entrySet()) { - List<DbUser> refreshed = refreshUsers(entry.getValue(), authzMap.get(entry.getKey())); - updates.addAll(refreshed); - } - - // Actually update the users in the database (note that this should be done with a batch update, but we don't - // have support for that yet): - for (DbUser dbUser : updates) { - dao.update(dbUser); - } + SyncUsers.sync(DbFacade.getInstance().getDbUserDao().getAll()); } - /** - * Refresh a list of users retrieving their data from a given directory. - * - * @param dbUsers the list of users to refresh - * @param authz the authz extension where the data of the users will be extracted from, it may be {@code null} if the - * directory has already been removed from the configuration - * @return the list of database users that have been actually modified and that need to be updated in the database - */ - private List<DbUser> refreshUsers(List<DbUser> dbUsers, ExtensionProxy authz) { - // Find all the users in the directory using a batch operation to improve performance: - Map<String, List<String>> idsPerNamespace = new HashMap<>(); - - List<DbUser> refreshed = new ArrayList<>(); - List<String> ids = new ArrayList<>(dbUsers.size()); - for (DbUser dbUser : dbUsers) { - MultiValueMapUtils.addToMap(dbUser.getNamespace(), dbUser.getExternalId(), idsPerNamespace); - } - for (String namespace : idsPerNamespace.keySet()) { - List<DirectoryUser> directoryUsers = null; - if (authz != null) { - directoryUsers = DirectoryUtils.findDirectoryUserByIds(authz, namespace, ids, true, false); - } - else { - directoryUsers = Collections.emptyList(); - } - - // Build a map of users indexed by directory id to simplify the next step where we want to find the directory - // user corresponding to each database user: - Map<String, DirectoryUser> index = new HashMap<>(); - for (DirectoryUser directoryUser : directoryUsers) { - index.put(directoryUser.getId(), directoryUser); - } - - // For each database user refresh it using the corresponding directory user and collect those users that need to - // be updated: - for (DbUser dbUser : dbUsers) { - DirectoryUser directoryUser = index.get(dbUser.getExternalId()); - if (directoryUser != null) { - dbUser.setActive(false); - // TODO: will be fixed in next patch in series - // dbUser.setGroupIds(DirectoryUtils.getGroupIdsFromUser(directoryUser)); - dbUser = refreshUser(dbUser, directoryUser); - if (dbUser != null) { - refreshed.add(dbUser); - } - } - } - - } - - return refreshed; - } - - /** - * Detect differences between a user as stored in the database and the same user retrieved from the directory. - * - * @param dbUser the database user - * @param directoryUser the directory user, it may be {@code null} if the user doesn't exist in the directory - * @return the updated database user if it was actually updated or {@code null} if it doesn't need to be updated - */ - private DbUser refreshUser(DbUser dbUser, DirectoryUser directoryUser) { - // If there the user doesn't exist in the directory then we only need to mark the database user as not active - // if it isn't marked already: - if (directoryUser == null) { - if (dbUser.isActive()) { - log.warnFormat( - "User \"{0}\" will be marked as not active as it wasn't found in the directory \"{1}\".", - dbUser.getLoginName(), dbUser.getDomain() - ); - } - return dbUser; - } - - // This flag indicates if there are any differences and thus if the database update should actually be - // performed: - boolean update = false; - - // If the user was marked as not active in the database then mark it as active: - if (!dbUser.isActive()) { - log.infoFormat( - "User \"{0}\" will be marked as active as it was found in directory \"{1}\".", - dbUser.getLoginName(), dbUser.getDomain() - ); - dbUser.setActive(true); - update = true; - } - - // Compare the attributes of the database user with those of the directory, copy those that changed and update - // the flag that indicates that the database needs to be updated: - if (!StringUtils.equals(dbUser.getFirstName(), directoryUser.getFirstName())) { - dbUser.setFirstName(directoryUser.getFirstName()); - update = true; - } - if (!StringUtils.equals(dbUser.getLastName(), directoryUser.getLastName())) { - dbUser.setLastName(directoryUser.getLastName()); - update = true; - } - if (!StringUtils.equals(dbUser.getDomain(), directoryUser.getDirectoryName())) { - dbUser.setDomain(directoryUser.getDirectoryName()); - update = true; - } - if (!StringUtils.equals(dbUser.getLoginName(), directoryUser.getName())) { - dbUser.setLoginName(directoryUser.getName()); - update = true; - } - if (!StringUtils.equals(dbUser.getDepartment(), directoryUser.getDepartment())) { - dbUser.setDepartment(directoryUser.getDepartment()); - update = true; - } - if (!StringUtils.equals(dbUser.getRole(), directoryUser.getTitle())) { - dbUser.setRole(directoryUser.getTitle()); - update = true; - } - if (!StringUtils.equals(dbUser.getEmail(), directoryUser.getEmail())) { - dbUser.setEmail(directoryUser.getEmail()); - update = true; - } - - // Compare the new list of group names and identifiers: - List<String> groupNamesFromDirectory = new ArrayList<>(); - DbGroupDAO groupDao = DbFacade.getInstance().getDbGroupDao(); - HashSet<Guid> groupIds = new HashSet<>(); - for (DirectoryGroup directoryGroup : directoryUser.getGroups()) { - DbGroup dbGroup = groupsMap.get(directoryGroup.getId()); - if (dbGroup == null) { - dbGroup = groupDao.getByExternalId(dbUser.getDomain(), directoryGroup.getId()); - } - if (dbGroup != null) { - groupIds.add(dbGroup.getId()); - } - groupNamesFromDirectory.add(directoryGroup.getName()); - } - Collections.sort(groupNamesFromDirectory); - List<String> groupNamesFromDb = new ArrayList<String>(dbUser.getGroupNames()); - Collections.sort(groupNamesFromDb); - if (!groupNamesFromDb.equals(groupNamesFromDirectory)) { - dbUser.setGroupNames(new HashSet<String>(groupNamesFromDirectory)); - update = true; - } - - if (!groupIds.equals(dbUser.getGroupIds())) { - dbUser.setGroupIds(groupIds); - update = true; - } - return update? dbUser: null; - } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DirectoryEntryKey.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DirectoryEntryKey.java new file mode 100644 index 0000000..c3964a9 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DirectoryEntryKey.java @@ -0,0 +1,60 @@ +package org.ovirt.engine.core.bll; + +import org.ovirt.engine.core.common.businessentities.DbUser; + + +public class DirectoryEntryKey { + + private String authz; + private String externalId; + + public DirectoryEntryKey(String authz, String externalId) { + this.authz = authz; + this.externalId = externalId; + } + + public DirectoryEntryKey(DbUser dbUser) { + this(dbUser.getDomain(), dbUser.getExternalId()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((authz == null) ? 0 : authz.hashCode()); + result = prime * result + ((externalId == null) ? 0 : externalId.hashCode()); + return result; + } + + public String getAuthz() { + return authz; + } + + public String getExternalId() { + return externalId; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DirectoryEntryKey other = (DirectoryEntryKey) obj; + if (authz == null) { + if (other.authz != null) + return false; + } else if (!authz.equals(other.authz)) + return false; + if (externalId == null) { + if (other.externalId != null) + return false; + } else if (!externalId.equals(other.externalId)) + return false; + return true; + } + +} + diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SyncUsers.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SyncUsers.java new file mode 100644 index 0000000..cb80065 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/SyncUsers.java @@ -0,0 +1,84 @@ +package org.ovirt.engine.core.bll; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.ovirt.engine.api.extensions.ExtMap; +import org.ovirt.engine.core.aaa.AuthzUtils; +import org.ovirt.engine.core.aaa.DirectoryUtils; +import org.ovirt.engine.core.common.businessentities.DbUser; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; +import org.ovirt.engine.core.extensions.mgr.ExtensionProxy; +import org.ovirt.engine.core.utils.collections.MultiValueMapUtils; +import org.ovirt.engine.core.utils.extensionsmgr.EngineExtensionsManager; +import org.ovirt.engine.core.utils.log.Log; +import org.ovirt.engine.core.utils.log.LogFactory; + +public class SyncUsers { + + private static final Log log = LogFactory.getLog(SyncUsers.class); + + public static void sync(List<DbUser> dbUsers) { + Map<String, Map<String, Set<String>>> authzToNamespaceToUserIds = new HashMap<>(); + Map<DirectoryEntryKey, DbUser> originalDbUsersMap = new HashMap<>(); + Map<String, List<DbUser>> dbUsersPerAuthz = new HashMap<>(); + + //Initialize the entries based on authz in the map + for (DbUser dbUser : dbUsers) { + MultiValueMapUtils.addToMap(dbUser.getDomain(), dbUser, dbUsersPerAuthz); + if (!authzToNamespaceToUserIds.containsKey(dbUser.getDomain())) { + authzToNamespaceToUserIds.put(dbUser.getDomain(), new HashMap<String, Set<String>>()); + } + MultiValueMapUtils.addToMapOfSets(dbUser.getNamespace(), dbUser.getExternalId(), authzToNamespaceToUserIds.get(dbUser.getDomain())); + originalDbUsersMap.put(new DirectoryEntryKey(dbUser), dbUser); + } + + for (Entry<String, Map<String, Set<String>>> entry : authzToNamespaceToUserIds.entrySet()) { + Map<String, DbUser> activeUsers = new HashMap<>(); + String authz = entry.getKey(); + try { + ExtensionProxy authzExtension = EngineExtensionsManager.getInstance().getExtensionByName(authz); + for (Entry<String, Set<String>> userIdsPerNamespace : entry.getValue().entrySet()) { + for ( + ExtMap principal : + AuthzUtils.fetchPrincipalsByIdsRecursively( + authzExtension, userIdsPerNamespace.getKey(), + new ArrayList<String>(userIdsPerNamespace.getValue())) + ) { + DirectoryUtils.flatGroups(principal); + DbUser dbUser = DirectoryUtils.mapPrincipalRecordToDbUser(authz, principal); + dbUser.setGroupIds(DirectoryUtils.getGroupIdsFromPrincipal(authz, principal)); + activeUsers.put(dbUser.getExternalId(), dbUser); + } + } + + for (DbUser dbUser : dbUsersPerAuthz.get(authz)) { + DbUser activeUser = activeUsers.get(dbUser.getExternalId()); + if (activeUser != null) { + if (!activeUser.equals(dbUser)) { + activeUser.setId(dbUser.getId()); + log.info(String.format("The user %1$s from authz extension %2$s got updated since last interval", + activeUser.getLoginName(), + activeUser.getDomain())); + DbFacade.getInstance().getDbUserDao().update(activeUser); + } + } else { + log.info(String.format("The user %1$s from authz extension %2$s could not be found, and will be marked as inactive", + dbUser.getLoginName(), + dbUser.getDomain())); + dbUser.setActive(false); + DbFacade.getInstance().getDbUserDao().update(dbUser); + } + } + } catch (Exception ex) { + log.error(String.format("Error during user synchronization of extension %1$s. Exception message is %2$s", + authz, ex.getMessage())); + log.debug("", ex); + } + } + } +} -- To view, visit http://gerrit.ovirt.org/29915 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I3a66a7c235f16ff26cac3a779de688c73d67f4a2 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.5 Gerrit-Owner: Yair Zaslavsky <yzasl...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches