/**
* Copyright (c) 2009--2015 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.manager.system;
import com.redhat.rhn.common.db.datasource.DataResult;
import com.redhat.rhn.common.db.datasource.ModeFactory;
import com.redhat.rhn.common.db.datasource.SelectMode;
import com.redhat.rhn.common.hibernate.LookupException;
import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.common.security.PermissionException;
import com.redhat.rhn.domain.entitlement.Entitlement;
import com.redhat.rhn.domain.role.RoleFactory;
import com.redhat.rhn.domain.server.EntitlementServerGroup;
import com.redhat.rhn.domain.server.ManagedServerGroup;
import com.redhat.rhn.domain.server.Server;
import com.redhat.rhn.domain.server.ServerGroup;
import com.redhat.rhn.domain.server.ServerGroupFactory;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.domain.user.UserFactory;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* ServerGroupManager
* @version $Rev$
*/
public class ServerGroupManager {
private static final ServerGroupManager MANAGER = new ServerGroupManager();
/**
* Singleton Instance to get manager object
* @return an instance of the manager
*/
public static ServerGroupManager getInstance() {
return MANAGER;
}
/**
* Private constructor.
*/
private ServerGroupManager() {
}
/**
* Lookup a ServerGroup by ID and organization.
* @param id Server group id
* @param user logged in user needed for authentication
* @return Server group requested
*/
public ManagedServerGroup lookup(Long id, User user) {
ManagedServerGroup sg = ServerGroupFactory.
lookupByIdAndOrg(id, user.getOrg());
if (sg == null) {
validateAccessCredentials(user, sg, id.toString());
}
else {
validateAccessCredentials(user, sg, sg.getName());
}
return sg;
}
/**
* Lookup a ServerGroup by ID and organization.
* @param name Server group name
* @param user logged in user needed for authentication
* @return Server group requested
*/
public ManagedServerGroup lookup(String name, User user) {
ManagedServerGroup sg = ServerGroupFactory.
lookupByNameAndOrg(name, user.getOrg());
validateAccessCredentials(user, sg, name);
return sg;
}
/**
* Returns an EntitlementServerGroup for a given entitlement type
* @param ent the entitlement type desired
* @param user logged in user needed for authentication -
* needs to be ORG Admin
* @return the Server group requested.
*/
public EntitlementServerGroup lookupEntitled(Entitlement ent, User user) {
validateOrgAdminCredentials(user);
EntitlementServerGroup sg = ServerGroupFactory.
lookupEntitled(ent, user.getOrg());
return sg;
}
/**
* Returns true if the the given user can
* administer server groups..
* This should be the baseline for us to load activation keys.
* @param user the user to check on
* @param group the server group object to authenticate.
* @return true if a key can be administered. False otherwise.
*/
public boolean canAccess(User user, ServerGroup group) {
if (user == null || group == null) {
return false;
}
if (!user.getOrg().equals(group.getOrg())) {
return false;
}
SelectMode m = ModeFactory.getMode("SystemGroup_queries", "is_visible");
Map<String, Object> params = new HashMap<String, Object>();
params.put("user_id", user.getId());
params.put("sgid", group.getId());
List result = m.execute(params);
return result.size() > 0;
}
/**
* validates that the given user can access
* the given ServerGroup object. Raises a permission exception
* if the combination is invalid..
* @param user the user to authenticate
* @param group the servergroup to authenticate
* @param groupIdentifier id or group name to use when reporting exception
* (group could be null)
*/
public void validateAccessCredentials(User user,
ServerGroup group, String groupIdentifier) {
if (group == null || (group.isManaged() && !canAccess(user, group))) {
LocalizationService ls = LocalizationService.getInstance();
LookupException e =
new LookupException("Unable to locate or access server group: " +
groupIdentifier);
e.setLocalizedTitle(ls.getMessage("lookup.servergroup.title"));
e.setLocalizedReason1(ls.getMessage("lookup.servergroup.reason1"));
e.setLocalizedReason2(ls.getMessage("lookup.servergroup.reason2"));
throw e;
}
}
/**
* validates that the given user can administer
* a server group. Raises a permission exception if administering
* is Not possible
* @param user the user to authenticate
*/
public void validateAdminCredentials(User user) {
if (!user.hasRole(RoleFactory.SYSTEM_GROUP_ADMIN)) {
String msg = "The desired operation cannot be performed since the user" +
"[" + user + "] does not have the system group admin role";
throw new PermissionException(msg);
}
}
/**
* validates that the given user can administer
* or lookup an entitled server group.
* Raises a permission exception if administering
* is Not possible
* @param user the user to authenticate
*/
public void validateOrgAdminCredentials(User user) {
if (!user.hasRole(RoleFactory.ORG_ADMIN)) {
String msg = "The desired operation cannot be performed since the user" +
"[" + user + "] does not have the Org Admin role";
throw new PermissionException(msg);
}
}
/**
* Removes an ServerGroup.
* @param user user object needed for authentication
* @param group the group to remove
*/
public void remove(User user, ManagedServerGroup group) {
validateAccessCredentials(user, group, group.getName());
validateAdminCredentials(user);
removeServers(group, listServers(group), user);
dissociateAdmins(group, group.getAssociatedAdminsFor(user), user);
ServerGroupFactory.remove(group);
}
/**
* Create a new Server group
* @param user user needed for authentication
* @param name the name of the server group
* @param description the description of the server group
* @return the created server group.
*/
public ManagedServerGroup create(User user, String name, String description) {
validateAdminCredentials(user);
ManagedServerGroup sg = ServerGroupFactory.create(name, description,
user.getOrg());
if (!user.hasRole(RoleFactory.ORG_ADMIN)) {
sg.getAssociatedAdminsFor(user).add(user);
ServerGroupFactory.save(sg);
UserFactory.save(user);
}
return sg;
}
/**
* Associates/Disocciates a list of admins to a server group
* by using User's login name.. This method had to be added
* to give access to a list of users to a
* server group admin. By default one needs Org Admin role
* to access/acquire user objects other than the loggedInUser.
* However according to the UI, Server Group Admin
* needs to be able to assign Users to Groups.
* (even if he cannot access the User's details)
* However our ServerGroup instances need full blown user objects
* to get mapped correctly.. Due to which this method was added.
* @param group the Servergroup to associate/dissociate users
* @param adminLogins the login names of the users to associate/dissociate
* @param associate true if we want to associate false otherwise.
* @param loggedInUser the logged in user.
*/
public void associateOrDissociateAdminsByLoginName(ManagedServerGroup group,
Collection adminLogins,
boolean associate,
User loggedInUser) {
validateAccessCredentials(loggedInUser, group, group.getName());
validateAdminCredentials(loggedInUser);
List admins = new LinkedList();
for (Iterator itr = adminLogins.iterator(); itr.hasNext();) {
String login = (String) itr.next();
User admin = UserFactory.lookupByLogin(login);
if (admin == null || !loggedInUser.getOrg().equals(admin.getOrg())) {
LocalizationService ls = LocalizationService.getInstance();
LookupException e = new LookupException("Could not find user " + login);
e.setLocalizedTitle(ls.getMessage("lookup.jsp.title.user"));
e.setLocalizedReason1(ls.getMessage("lookup.jsp.reason1.user"));
e.setLocalizedReason2(ls.getMessage("lookup.jsp.reason2.user"));
throw e;
}
admins.add(admin);
}
if (associate) {
associateAdmins(group, admins, loggedInUser);
}
else {
dissociateAdmins(group, admins, loggedInUser);
}
}
/**
* Associates a bunch of administrators to a server group
* @param sg the server group to process
* @param admins a collection of users to add as administrators
* @param loggedInUser the loggedInUser needed for credentials
*/
public void associateAdmins(ManagedServerGroup sg, Collection admins,
User loggedInUser) {
validateAccessCredentials(loggedInUser, sg, sg.getName());
validateAdminCredentials(loggedInUser);
Set adminSet = sg.getAssociatedAdminsFor(loggedInUser);
processAdminList(sg, admins, loggedInUser);
adminSet.addAll(admins);
ServerGroupFactory.save(sg);
UserFactory factory = UserFactory.getInstance();
for (Iterator itr = admins.iterator(); itr.hasNext();) {
User u = (User) itr.next();
factory.syncServerGroupPerms(u);
}
}
/**
* Disssociates a bunch of administrators from a server group
* @param sg the server group to process
* @param admins a collection of administrators to deassociate
* @param loggedInUser the loggedInUser needed for credentials
*/
public void dissociateAdmins(ManagedServerGroup sg, Collection admins,
User loggedInUser) {
validateAccessCredentials(loggedInUser, sg, sg.getName());
validateAdminCredentials(loggedInUser);
Set adminSet = sg.getAssociatedAdminsFor(loggedInUser);
processAdminList(sg, admins, loggedInUser);
admins.remove(loggedInUser); //can't disassociate thyself.
adminSet.removeAll(admins);
ServerGroupFactory.save(sg);
for (Iterator itr = admins.iterator(); itr.hasNext();) {
User u = (User) itr.next();
UserFactory.save(u);
}
}
/**
* @param sg the server group to process
* @param admins a collection of users to authenticate
* @param loggedInUser the loggedInUser needed for credentials
*/
private void processAdminList(ServerGroup sg, Collection admins,
User loggedInUser) {
for (Iterator itr = admins.iterator(); itr.hasNext();) {
User user = (User) itr.next();
if (!user.getOrg().equals(loggedInUser.getOrg())) {
String msg = "Invalid Administrator.[" + user + "]." +
"Unable to add the given administrator to" +
" the servergroup [" + sg + "] because the org of" +
" the user does NOT belong to the org of the server group";
throw new PermissionException(msg);
}
if (user.hasRole(RoleFactory.ORG_ADMIN)) {
//we are not in the business of
//adding or removing org admins..
itr.remove();
}
}
}
/**
* Associates a bunch of servers to a server group
* @param sg the server group to process
* @param servers a collection of servers to add.
* @param loggedInUser the loggedInUser needed for credentials
*/
public void addServers(ServerGroup sg, Collection<Server> servers, User loggedInUser) {
validateAccessCredentials(loggedInUser, sg, sg.getName());
validateAdminCredentials(loggedInUser);
for (Server s : servers) {
SystemManager.addServerToServerGroup(s, sg);
}
}
/**
* Dissociates a bunch of servers from a server group
* @param sg the server group to process
* @param servers a collection of servers to dissociate
* @param loggedInUser the loggedInUser needed for credentials
*/
public void removeServers(ServerGroup sg, Collection<Server> servers,
User loggedInUser) {
validateAccessCredentials(loggedInUser, sg, sg.getName());
validateAdminCredentials(loggedInUser);
removeServers(sg, servers);
}
/**
* Dissociates a bunch of servers from a server group.
* **WARNING** This method does not validate the user's access or
* admin credentials; therefore, it should be used with caution.
* @param sg the server group to process
* @param servers a collection of servers to dissociate
*/
public void removeServers(ServerGroup sg, Collection<Server> servers) {
for (Server s : servers) {
SystemManager.removeServerFromServerGroup(s, sg);
}
}
/**
* Returns the admins of a given servergroup. This list includes
* ORG ADMINS + Associated Admins.. so this is different from
* sg.getAssociatedAdmins()
* @param sg the server group that you want the admin list for.
* @param loggedInUser the loggedInUser needed for credentials
* @return list of User objects that can administer the server group
*/
public List listAdministrators(ManagedServerGroup sg, User loggedInUser) {
validateAccessCredentials(loggedInUser, sg, sg.getName());
validateAdminCredentials(loggedInUser);
return ServerGroupFactory.listAdministrators(sg);
}
/**
* Returns a list of servergroups that have NO administrators
* associated to it.
* Note this requires ORG_ADMIN access so that the
* administrator can access ALL servergroups.
* @param user ORG_ADMIN user.
* @return a list of server groups
*/
public List listNoAdminGroups(User user) {
if (!user.hasRole(RoleFactory.ORG_ADMIN)) {
String msg = "The desired operation cannot be performed since the user" +
"[" + user + "] does not have the org admin role";
throw new PermissionException(msg);
}
return ServerGroupFactory.listNoAdminGroups(user.getOrg());
}
/**
* Returns the servers of a given servergroup
* @param sg the server group to find the servers of
* @return list of Server objects that are a part of the given server group.
*/
public List<Server> listServers(ServerGroup sg) {
return ServerGroupFactory.listServers(sg);
}
/**
* List all servers that have checked in within a X days
* @param sg the sever group
* @param threshold the number of days a system needs to have checked in by
* @return list of system ids
*/
public List<Long> listActiveServers(ServerGroup sg, Long threshold) {
return ServerGroupFactory.listActiveServerIds(sg, threshold);
}
/**
* List all servers that have not checked in in X days
* @param sg the sever group
* @param threshold the number of days a system needs to have not checked in by
* @return list of system ids
*/
public List<Long> listInactiveServers(ServerGroup sg, Long threshold) {
return ServerGroupFactory.listInactiveServerIds(sg, threshold);
}
/**
* Returns counts of applicable errata to given server group.
* @param user the user to get org from
* @param group the server group object to get counts
* @return map with counts of security, bugfix and enhancement errata
*/
public Map errataCounts(User user, ServerGroup group) {
SelectMode m = ModeFactory.getMode("SystemGroup_queries", "group_errata_counts");
Map<String, Object> params = new HashMap<String, Object>();
params.put("org_id", user.getOrg().getId());
params.put("sgid", group.getId());
DataResult result = m.execute(params);
return (Map) result.get(0);
}
}