/** * 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. */ package com.redhat.rhn.manager.action; import com.redhat.rhn.domain.action.Action; import com.redhat.rhn.domain.action.ActionChain; import com.redhat.rhn.domain.action.ActionChainFactory; import com.redhat.rhn.domain.action.ActionFactory; import com.redhat.rhn.domain.action.ActionType; import com.redhat.rhn.domain.action.config.ConfigAction; import com.redhat.rhn.domain.action.rhnpackage.PackageAction; import com.redhat.rhn.domain.action.script.ScriptActionDetails; import com.redhat.rhn.domain.action.script.ScriptRunAction; import com.redhat.rhn.domain.errata.Errata; import com.redhat.rhn.domain.server.Server; import com.redhat.rhn.domain.server.ServerFactory; import com.redhat.rhn.domain.user.User; import com.redhat.rhn.manager.errata.ErrataManager; import com.redhat.rhn.manager.system.SystemManager; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; /** * An ActionManager companion to deal with Action Chains. * * Methods in this class are intended to replace similar methods in * ActionManager adding Action Chains support. It was decided to keep * this class separate to avoid adding significant complexity to ActionManager. * @author Silvio Moioli <smoioli@suse.de> */ public class ActionChainManager { /** * Utility class constructor. */ private ActionChainManager() { } /** * Schedules s package installation on a server. * @param user the user scheduling actions * @param server the server * @param packages the packages * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled action * @see com.redhat.rhn.manager.action.ActionManager#schedulePackageInstall */ public static PackageAction schedulePackageInstall(User user, Server server, List<Map<String, Long>> packages, Date earliest, ActionChain actionChain) { return schedulePackageActionByOs(user, server, packages, earliest, actionChain, null, ActionFactory.TYPE_PACKAGES_UPDATE); } /** * Schedules s package removal on a server. * @param user the user scheduling actions * @param server the server * @param packages the packages * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled action * @see com.redhat.rhn.manager.action.ActionManager#schedulePackageRemoval */ public static PackageAction schedulePackageRemoval(User user, Server server, List<Map<String, Long>> packages, Date earliest, ActionChain actionChain) { return schedulePackageActionByOs(user, server, packages, earliest, actionChain, null, ActionFactory.TYPE_PACKAGES_REMOVE); } /** * Schedules package upgrade(s) for the given servers. * Note: package upgrade = package install * @param user the user scheduling actions * @param packageMaps maps system IDs to lists of "package maps" * @param earliestAction Date of earliest action to be executed * @param actionChain the action chain or null * @return scheduled actions * @see ActionManager#addPackageActionDetails(Action, List) for "package map" */ public static List<Action> schedulePackageUpgrades(User user, Map<Long, List<Map<String, Long>>> packageMaps, Date earliestAction, ActionChain actionChain) { List<Action> actions = new ArrayList<Action>(); Integer sortOrder = null; if (actionChain != null) { sortOrder = ActionChainFactory.getNextSortOrderValue(actionChain); } for (Long sid : packageMaps.keySet()) { Server server = SystemManager.lookupByIdAndUser(sid, user); actions.add(schedulePackageActionByOs(user, server, packageMaps.get(sid), earliestAction, actionChain, sortOrder, ActionFactory.TYPE_PACKAGES_UPDATE)); } return actions; } /** * Schedules a package upgrade for the given server. * @param user the user scheduling actions * @param server the server * @param packages a list of "package maps" * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled action * @see ActionManager#addPackageActionDetails(Action, List) for "package map" */ public static PackageAction schedulePackageUpgrade(User user, Server server, List<Map<String, Long>> packages, Date earliest, ActionChain actionChain) { return schedulePackageInstall(user, server, packages, earliest, actionChain); } /** * Schedules a package verification for the given server. * @param user the user scheduling actions * @param server the server * @param packages a list of "package maps" * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled action * @see com.redhat.rhn.manager.action.ActionManager#schedulePackageVerify * @see ActionManager#addPackageActionDetails(Action, List) for "package map" */ public static PackageAction schedulePackageVerify(User user, Server server, List<Map<String, Long>> packages, Date earliest, ActionChain actionChain) { return (PackageAction) schedulePackageAction(user, packages, ActionFactory.TYPE_PACKAGES_VERIFY, earliest, actionChain, null, server); } /** * Schedules a generic package action on a single server. * @param user the user scheduling actions * @param packages a list of "package maps" * @param type the type * @param earliest the earliest execution date * @param actionChain the action chain or null * @param sortOrder the sort order or null * @param server the server * @return scheduled action * @see com.redhat.rhn.manager.action.ActionManager#schedulePackageAction * @see ActionManager#addPackageActionDetails(Action, List) for "package map" */ private static Action schedulePackageAction(User user, List<Map<String, Long>> packages, ActionType type, Date earliest, ActionChain actionChain, Integer sortOrder, Server server) { Set<Long> serverIds = new HashSet<Long>(); serverIds.add(server.getId()); return schedulePackageActions(user, packages, type, earliest, actionChain, sortOrder, serverIds).iterator().next(); } /** * Schedules generic package actions on multiple servers. * @param user the user scheduling actions * @param packages a list of "package maps" * @param type the type * @param earliest the earliest execution date * @param actionChain the action chain or null * @param sortOrder the sort order or null * @param servers the servers involved * @return scheduled actions * @see com.redhat.rhn.manager.action.ActionManager#schedulePackageAction * @see ActionManager#addPackageActionDetails(Action, List) for "package map" */ private static Set<Action> schedulePackageActions(User user, List<Map<String, Long>> packages, ActionType type, Date earliestAction, ActionChain actionChain, Integer sortOrder, Set<Long> serverIds) { String name = ActionManager.getActionName(type); Set<Action> result = scheduleActions(user, type, name, earliestAction, actionChain, sortOrder, serverIds); for (Action action : result) { ActionManager.addPackageActionDetails(action, packages); } return result; } /** * Schedules script actions for the given servers. * @param user the user scheduling actions * @param sids IDs of affected servers * @param script detail object of the script to run * @param name name of the script action * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions * @throws com.redhat.rhn.manager.MissingCapabilityException if any server * in the list is missing script.run schedule fails * @throws com.redhat.rhn.manager.MissingEntitlementException if any server * in the list is missing Provisioning schedule fails * @see com.redhat.rhn.manager.action.ActionManager#scheduleScriptRun * @see ActionManager#addPackageActionDetails(Action, List) for "package map" */ public static Set<Action> scheduleScriptRuns(User user, List<Long> sids, String name, ScriptActionDetails script, Date earliest, ActionChain actionChain) { ActionManager.checkScriptingOnServers(sids); Set<Long> sidSet = new HashSet<Long>(); sidSet.addAll(sids); Set<Action> result = scheduleActions(user, ActionFactory.TYPE_SCRIPT_RUN, name, earliest, actionChain, null, sidSet); for (Action action : result) { ScriptActionDetails actionScript = ActionFactory.createScriptActionDetails( script.getUsername(), script.getGroupname(), script.getTimeout(), script.getScriptContents()); ((ScriptRunAction)action).setScriptActionDetails(actionScript); ActionFactory.save(action); } return result; } /** * Creates configuration actions for the given server IDs. * @param user the user scheduling actions * @param revisions a set of revision IDs * @param serverIds a set of server IDs * @param type the type of configuration action * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions */ public static Set<Action> createConfigActions(User user, Collection<Long> revisions, Collection<Long> serverIds, ActionType type, Date earliest, ActionChain actionChain) { List <Server> servers = SystemManager.hydrateServerFromIds(serverIds, user); return createConfigActionForServers(user, revisions, servers, type, earliest, actionChain); } /** * Creates configuration actions for the given servers. * @param user the user scheduling actions * @param revisions a set of revision IDs * @param servers a set of servers * @param type the type of configuration action * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions */ public static Set<Action> createConfigActionForServers(User user, Collection<Long> revisions, Collection<Server> servers, ActionType type, Date earliest, ActionChain actionChain) { Set<Action> result = new HashSet<Action>(); if (actionChain == null) { Action action = ActionManager.createConfigActionForServers(user, revisions, servers, type, earliest); if (action != null) { result.add(action); } } else { for (Server server : servers) { ConfigAction action = ActionManager .createConfigAction(user, type, earliest); ActionManager.checkConfigActionOnServer(type, server); ActionChainFactory.queueActionChainEntry(action, actionChain, server); ActionManager.addConfigurationRevisionsToAction(user, revisions, action, server); ActionFactory.save(action); result.add(action); } } return result; } /** * Creates configuration actions from server-revision maps. * @param user the user scheduling actions * @param revisions maps servers to multiple revision IDs * @param serverIds a set of server IDs * @param type the type of configuration action * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions */ public static Set<Action> createConfigActions(User user, Map<Long, Collection<Long>> revisions, Collection<Long> serverIds, ActionType type, Date earliest, ActionChain actionChain) { List <Server> servers = SystemManager.hydrateServerFromIds(serverIds, user); return createConfigActionForServers(user, revisions, servers, type, earliest, actionChain); } /** * Creates configuration actions from server-revision maps. * @param user the user scheduling actions * @param revisions maps servers to multiple revision IDs * @param servers a set of server objects * @param type the type of configuration action * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions */ public static Set<Action> createConfigActionForServers(User user, Map<Long, Collection<Long>> revisions, Collection<Server> servers, ActionType type, Date earliest, ActionChain actionChain) { Set<Action> result = new HashSet<Action>(); if (actionChain == null) { ConfigAction action = ActionManager.createConfigAction(user, type, earliest); ActionFactory.save(action); for (Server server : servers) { ActionManager.checkConfigActionOnServer(type, server); ActionFactory.addServerToAction(server.getId(), action); ActionManager.addConfigurationRevisionsToAction(user, revisions.get(server.getId()), action, server); ActionFactory.save(action); result.add(action); } } else { int sortOrder = ActionChainFactory.getNextSortOrderValue(actionChain); for (Server server : servers) { ConfigAction action = ActionManager .createConfigAction(user, type, earliest); ActionFactory.save(action); result.add(action); ActionManager.checkConfigActionOnServer(type, server); ActionChainFactory.queueActionChainEntry(action, actionChain, server, sortOrder); ActionManager.addConfigurationRevisionsToAction(user, revisions.get(server.getId()), action, server); ActionFactory.save(action); result.add(action); } } return result; } /** * Schedules a reboot action on a server. * @param user the user scheduling actions * @param server the affected server * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions */ public static Action scheduleRebootAction(User user, Server server, Date earliest, ActionChain actionChain) { Set<Long> serverIds = new HashSet<Long>(); serverIds.add(server.getId()); Set<Action> actions = scheduleRebootActions(user, serverIds, earliest, actionChain); return actions.iterator().next(); } /** * Schedules one or more reboot actions on multiple servers. * @param user the user scheduling actions * @param serverIds the affected servers' IDs * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions */ public static Set<Action> scheduleRebootActions(User user, Set<Long> serverIds, Date earliest, ActionChain actionChain) { Set<Action> actions = scheduleActions(user, ActionFactory.TYPE_REBOOT, ActionFactory.TYPE_REBOOT.getName(), earliest, actionChain, null, serverIds); return actions; } /** * Schedules an Errata update on a server. * @param user the user scheduling actions * @param server the affected server * @param errataIds a list of erratas IDs * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions */ public static Action scheduleErrataUpdate(User user, Server server, List<Integer> errataIds, Date earliest, ActionChain actionChain) { Set<Long> serverIds = new HashSet<Long>(); serverIds.add(server.getId()); Set<Action> actions = scheduleErrataUpdates(user, serverIds, errataIds, earliest, actionChain); return actions.iterator().next(); } /** * Schedules one or more Errata updates on multiple servers. * @param user the user scheduling actions * @param serverIds the affected servers' IDs * @param errataIds a list of erratas IDs * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions */ public static Set<Action> scheduleErrataUpdates(User user, Set<Long> serverIds, List<Integer> errataIds, Date earliest, ActionChain actionChain) { Set<Action> actions = new HashSet<Action>(); for (Integer errataId : errataIds) { Errata currErrata = ErrataManager.lookupErrata(Long.valueOf(errataId), user); Action update = ActionManager.createErrataAction(user, currErrata); ActionManager.storeAction(update); int sortOrder = ActionChainFactory.getNextSortOrderValue(actionChain); for (Long serverId : serverIds) { ActionChainFactory.queueActionChainEntry(update, actionChain, serverId, sortOrder); } actions.add(update); } return actions; } /** * Schedules one or more package installation actions on one or more servers. * @param user the user scheduling actions * @param serverIds the affected servers' IDs * @param packages a list of "package maps" * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions * @see ActionManager#addPackageActionDetails(Action, List) for "package map" */ public static List<Action> schedulePackageInstalls(User user, Collection<Long> serverIds, List<Map<String, Long>> packages, Date earliest, ActionChain actionChain) { return schedulePackageActionsByOs(user, serverIds, packages, earliest, actionChain, ActionFactory.TYPE_PACKAGES_UPDATE); } /** * Schedules one or more package removal actions on one or more servers. * @param user the user scheduling actions * @param serverIds the affected servers' IDs * @param packages a list of "package maps" * @param earliest the earliest execution date * @param actionChain the action chain or null * @return scheduled actions * @see ActionManager#addPackageActionDetails(Action, List) for "package map" */ public static List<Action> schedulePackageRemovals(User user, Collection<Long> serverIds, List<Map<String, Long>> packages, Date earliest, ActionChain actionChain) { return schedulePackageActionsByOs(user, serverIds, packages, earliest, actionChain, ActionFactory.TYPE_PACKAGES_REMOVE); } /** * Schedules generic actions on multiple servers. * @param user the user scheduling actions * @param type the type * @param name the name * @param earliest the earliest execution date * @param actionChain the action chain or null * @param sortOrder the sort order or null * @param serverIds the affected servers' IDs * @return scheduled actions * @see com.redhat.rhn.manager.action.ActionManager#scheduleAction */ private static Set<Action> scheduleActions(User user, ActionType type, String name, Date earliest, ActionChain actionChain, Integer sortOrder, Set<Long> serverIds) { Set<Action> result = new HashSet<Action>(); if (actionChain == null) { Action action = ActionManager.createAction(user, type, name, earliest); ActionManager.scheduleForExecution(action, serverIds); result.add(action); } else { Integer nextSortOrder = sortOrder; if (sortOrder == null) { nextSortOrder = ActionChainFactory.getNextSortOrderValue(actionChain); } for (Long serverId : serverIds) { Action action = ActionManager.createAction(user, type, name, earliest); ActionChainFactory.queueActionChainEntry(action, actionChain, serverId, nextSortOrder); result.add(action); } } return result; } /** * Schedules package actions. * @param user the user scheduling actions * @param server the server * @param packages the packages * @param earliest the earliest execution date * @param actionChain the action chain or null * @param sortOrder the sort order or null * @param linuxActionType the action type to apply to Linux servers * @return scheduled action */ private static PackageAction schedulePackageActionByOs(User user, Server server, List<Map<String, Long>> packages, Date earliest, ActionChain actionChain, Integer sortOrder, ActionType linuxActionType) { return (PackageAction) schedulePackageAction(user, packages, linuxActionType, earliest, actionChain, sortOrder, server); } /** * Schedules package actions. * @param user the user scheduling actions * @param serverIds the affected servers' IDs * @param packages the packages involved * @param earliest the earliest execution date * @param actionChain the action chain or null * @param linuxActionType the action type to apply to Linux servers * @return scheduled actions */ private static List<Action> schedulePackageActionsByOs(User user, Collection<Long> serverIds, List<Map<String, Long>> packages, Date earliest, ActionChain actionChain, ActionType linuxActionType) { List<Action> result = new LinkedList<Action>(); Set<Long> rhelServers = new HashSet<Long>(); rhelServers.addAll(ServerFactory.listLinuxSystems(serverIds)); if (!rhelServers.isEmpty()) { result.addAll(schedulePackageActions(user, packages, linuxActionType, earliest, actionChain, null, rhelServers)); } return result; } }