/** * Copyright (c) 2014 SUSE LLC * * 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. */ /** * Copyright (c) 2014 Red Hat, Inc. */ package com.redhat.rhn.domain.action; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.hibernate.ObjectNotFoundException; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import com.redhat.rhn.common.hibernate.HibernateFactory; import com.redhat.rhn.domain.server.Server; import com.redhat.rhn.domain.user.User; import com.redhat.rhn.frontend.dto.SystemOverview; /** * Creates Action Chain related objects. * @author Silvio Moioli <smoioli@suse.de> */ public class ActionChainFactory extends HibernateFactory { /** Logger instance */ private static Logger log = Logger.getLogger(ActionChainFactory.class); /** Singleton instance */ private static ActionChainFactory singleton = new ActionChainFactory(); /** * Default constructor. */ private ActionChainFactory() { super(); } /** * Gets an action chain by label. * @param requestor the user whose chain we're looking for * @param label the label * @return the Action Chain or null if not found */ public static ActionChain getActionChain(User requestor, String label) { log.debug("Looking up Action Chain with label " + label); return (ActionChain) getSession() .createCriteria(ActionChain.class) .add(Restrictions.eq("label", label)) .add(Restrictions.eq("user", requestor)) .uniqueResult(); } /** * Gets an Action Chain by id. * @param requestor the user whose chain we're looking for * @param id the id * @return the Action Chain * @throws ObjectNotFoundException if there is no such id accessible to the requestor */ public static ActionChain getActionChain(User requestor, Long id) throws ObjectNotFoundException { log.debug("Looking up Action Chain with id " + id); if (id == null) { return null; } ActionChain ac = (ActionChain) getSession() .createCriteria(ActionChain.class) .add(Restrictions.eq("id", id)) .add(Restrictions.eq("user", requestor)) .uniqueResult(); if (ac == null) { throw new ObjectNotFoundException(ActionChain.class, "ActionChain Id " + id + " not found for User " + requestor.getLogin()); } return ac; } /** * Gets an Action Chain Entry by id. * @param requestor the user whose entry we're looking for * @param id the action chain entry id * @return the Action Chain Entry * @throws ObjectNotFoundException if there is no such id accessible to the requestor */ public static ActionChainEntry getActionChainEntry(User requestor, Long id) throws ObjectNotFoundException { if (id == null) { return null; } ActionChainEntry ace = (ActionChainEntry) getSession() .load(ActionChainEntry.class, id); if (ace.getActionChain().getUser().getId().longValue() == requestor.getId().longValue()) { return ace; } throw new ObjectNotFoundException(ActionChainEntry.class, "ActionChainEntry Id " + id + " not found for User " + requestor.getLogin()); } /** * Creates a new ActionChain object. * @param label the label * @param user the user * @return the action chain */ public static ActionChain createActionChain(String label, User user) { log.debug("Creating Action Chain with label " + label); ActionChain result = new ActionChain(); result.setLabel(label); result.setUser(user); singleton.saveObject(result); return result; } /** * Looks for an action chain by label, and creates one if not found. * @param label the label * @param user the currently logged in user * @return the action chain */ public static ActionChain getOrCreateActionChain(String label, User user) { ActionChain result = getActionChain(user, label); if (result != null) { return result; } return createActionChain(label, user); } /** * Creates a new entry in an Action Chain object, sort order will be * incremented. * @param action the action * @param actionChain the action chain * @param server the server * @return the action chain entry */ public static ActionChainEntry queueActionChainEntry(Action action, ActionChain actionChain, Server server) { int nextSortOrder = getNextSortOrderValue(actionChain); return queueActionChainEntry(action, actionChain, server, nextSortOrder); } /** * Creates a new entry in an Action Chain object. * @param action the action * @param actionChain the action chain * @param server the server * @param sortOrder the required sort order * @return the action chain entry */ public static ActionChainEntry queueActionChainEntry(Action action, ActionChain actionChain, Server server, int sortOrder) { log.debug("Queuing action " + action + " to Action Chain " + actionChain + " with sort order " + sortOrder); ActionChainEntry result = new ActionChainEntry(); result.setAction(action); result.setServer(server); result.setSortOrder(sortOrder); result.setActionChain(actionChain); actionChain.getEntries().add(result); actionChain.setModified(new Date()); return result; } /** * Creates a new entry in an Action Chain object. * @param action the action * @param actionChain the action chain * @param serverId the server id * @return the action chain entry */ public static ActionChainEntry queueActionChainEntry(Action action, ActionChain actionChain, Long serverId) { // this does not hit the database, as it returns a lazy object Server server = (Server) getSession().load(Server.class, serverId); return queueActionChainEntry(action, actionChain, server); } /** * Creates a new entry in an Action Chain object. * @param action the action * @param actionChain the action chain * @param serverId the server id * @param sortOrder the required sort order * @return the action chain entry */ public static ActionChainEntry queueActionChainEntry(Action action, ActionChain actionChain, Long serverId, int sortOrder) { Server server = (Server) getSession().load(Server.class, serverId); return queueActionChainEntry(action, actionChain, server, sortOrder); } /** * Creates a new entry in an Action Chain object. * * @param action the action * @param actionChain the action chain * @param systemOverview the server overview object * @return the action chain entry */ public static ActionChainEntry queueActionChainEntry(Action action, ActionChain actionChain, SystemOverview systemOverview) { return queueActionChainEntry(action, actionChain, systemOverview.getId()); } /** * Gets all action chains for a user. * @param requestor the user whose chains we're looking for * @return action chains */ @SuppressWarnings("unchecked") public static List<ActionChain> getActionChains(User requestor) { return getSession() .createCriteria(ActionChain.class) .add(Restrictions.eq("user", requestor)) .addOrder(Order.asc("label")) .list(); } /** * Gets all action chains, by modification date. * @param requestor the user whose chain we're looking for * @return action chains */ @SuppressWarnings("unchecked") public static List<ActionChain> getActionChainsByModificationDate(User requestor) { return getSession() .createCriteria(ActionChain.class) .add(Restrictions.eq("user", requestor)) .addOrder(Order.desc("modified")) .list(); } /** * Returns ActionChainEntryGroupDto objects corresponding to groups of * Action Chain entries with the same sort order and action type. * @param actionChain an Action Chain * @return a list of corresponding groups */ @SuppressWarnings("unchecked") public static List<ActionChainEntryGroup> getActionChainEntryGroups( final ActionChain actionChain) { return singleton.listObjectsByNamedQuery( "ActionChainEntry.getGroups", new HashMap<String, Object>() { { put("id", actionChain.getId()); } } ); } /** * Returns entries from a chain having a certain sort order number * @param actionChain the chain * @param sortOrder the sort order * @return an entry list */ @SuppressWarnings("unchecked") public static List<ActionChainEntry> getActionChainEntries( final ActionChain actionChain, final Integer sortOrder) { return singleton.listObjectsByNamedQuery( "ActionChainEntry.getActionChainEntries", new HashMap<String, Object>() { { put("id", actionChain.getId()); put("sortOrder", sortOrder); } } ); } /** * Gets the next sort order value. * @param actionChain the action chain * @return the next sort order value */ public static int getNextSortOrderValue(final ActionChain actionChain) { return (Integer) singleton.lookupObjectByNamedQuery( "ActionChain.getNextSortOrderValue", new HashMap<String, Object>() { { put("id", actionChain.getId()); } } ); } /** * Deletes an Action Chain and all associated objects. * @param actionChain the action chain to delete */ public static void delete(ActionChain actionChain) { log.debug("Deleting Action Chain " + actionChain); singleton.removeObject(actionChain); } /** * Schedules an Action Chain for execution. * @param actionChain the action chain to execute * @param date first action's minimum timestamp */ public static void schedule(ActionChain actionChain, Date date) { log.debug("Scheduling Action Chain " + actionChain + " to date " + date); Map<Server, Action> latest = new HashMap<Server, Action>(); int maxSortOrder = getNextSortOrderValue(actionChain); for (int sortOrder = 0; sortOrder < maxSortOrder; sortOrder++) { for (ActionChainEntry entry : getActionChainEntries(actionChain, sortOrder)) { Server server = entry.getServer(); Action action = entry.getAction(); log.debug("Scheduling Action " + action + " to server " + server); ActionFactory.addServerToAction(server.getId(), action); action.setPrerequisite(latest.get(server)); action.setEarliestAction(date); latest.put(server, action); } } log.debug("Action Chain " + actionChain + " scheduled to date " + date + ", deleting"); delete(actionChain); } /** * {@inheritDoc} */ @Override protected Logger getLogger() { return log; } /** * Remove gaps from entries in an action chain * * @param actionChain An ActionChain from which to be removed. * @param removedOrder sort order of the (already) removed entry */ public static void removeActionChainEntrySortGaps(ActionChain actionChain, int removedOrder) { Set<ActionChainEntry> entries = actionChain.getEntries(); for (ActionChainEntry entry : entries) { if (entry.getSortOrder() == removedOrder) { return; } } for (ActionChainEntry entry : entries) { if (entry.getSortOrder() > removedOrder) { entry.setSortOrder(entry.getSortOrder() - 1); } } } /** * Remove an entry from the action chain * * @param actionChain An ActionChain from which to be removed. * @param entry entry to remove */ public static void removeActionChainEntry(ActionChain actionChain, ActionChainEntry entry) { actionChain.getEntries().remove(entry); removeActionChainEntrySortGaps(actionChain, entry.getSortOrder()); } }