java/code/src/com/redhat/rhn/common/messaging/MessageQueue.java | 7 java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ScheduleRemoteCommand.java | 8 java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageInstallationAction.java | 77 +- java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageRemoveAction.java | 30 java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageUpgradeAction.java | 19 java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/ScheduleRemoteCommand.java | 354 ++++++++++ java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectInstallationPackagesAction.java | 23 java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectRemovePackagesAction.java | 3 java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectUpgradePackagesAction.java | 3 java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesAction.java | 100 +- java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesEvent.java | 83 +- java/code/src/com/redhat/rhn/frontend/events/SsmPackageEvent.java | 103 ++ java/code/src/com/redhat/rhn/frontend/events/SsmPackagesAction.java | 168 ++++ java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesAction.java | 129 +-- java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesEvent.java | 66 - java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesAction.java | 94 -- java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesEvent.java | 69 - java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml | 12 java/code/src/com/redhat/rhn/frontend/struts/RequestContext.java | 3 java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java | 4 java/code/src/com/redhat/rhn/manager/MissingCapabilityException.java | 14 java/code/src/com/redhat/rhn/manager/action/ActionManager.java | 89 +- java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java | 21 java/code/webapp/WEB-INF/pages/ssm/packageinstallschedule.jsp | 5 java/code/webapp/WEB-INF/pages/ssm/packagelist.jsp | 2 java/code/webapp/WEB-INF/pages/ssm/packageremoveschedule.jsp | 5 java/code/webapp/WEB-INF/pages/ssm/packagescheduleremote.jsp | 80 ++ java/code/webapp/WEB-INF/pages/ssm/packageupgradeschedule.jsp | 5 java/code/webapp/WEB-INF/struts-config.xml | 19 29 files changed, 1172 insertions(+), 423 deletions(-)
New commits: commit 9b323f2872082872093624a063af564fdb4c19b3 Author: Grant Gainey ggainey@redhat.com Date: Thu Apr 4 11:27:53 2013 -0400
947205: Allow remote-cmd as part of SSM Package install/update/remove * Refactored Ssm*PackageEvent/Action * Corrected error-messaging when systems missing required capability/entitlement
diff --git a/java/code/src/com/redhat/rhn/common/messaging/MessageQueue.java b/java/code/src/com/redhat/rhn/common/messaging/MessageQueue.java index 0c2812e..30eadb3 100644 --- a/java/code/src/com/redhat/rhn/common/messaging/MessageQueue.java +++ b/java/code/src/com/redhat/rhn/common/messaging/MessageQueue.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2012 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -35,6 +35,7 @@ import com.redhat.rhn.frontend.events.SsmChangeChannelSubscriptionsAction; import com.redhat.rhn.frontend.events.SsmChangeChannelSubscriptionsEvent; import com.redhat.rhn.frontend.events.SsmDeleteServersAction; import com.redhat.rhn.frontend.events.SsmDeleteServersEvent; +import com.redhat.rhn.frontend.events.SsmPackagesAction; import com.redhat.rhn.frontend.events.TraceBackAction; import com.redhat.rhn.frontend.events.TraceBackEvent; import com.redhat.rhn.frontend.events.UpdateErrataCacheAction; @@ -272,7 +273,7 @@ public class MessageQueue { SsmDeleteServersEvent.class);
// Used to allow SSM package installs to be run asynchronously - SsmInstallPackagesAction ssmPackageInstallAction = new SsmInstallPackagesAction(); + SsmPackagesAction ssmPackageInstallAction = new SsmInstallPackagesAction(); MessageQueue.registerAction(ssmPackageInstallAction, SsmInstallPackagesEvent.class);
SsmRemovePackagesAction ssmRpa = new SsmRemovePackagesAction(); @@ -281,7 +282,7 @@ public class MessageQueue { SsmVerifyPackagesAction ssmVpa = new SsmVerifyPackagesAction(); MessageQueue.registerAction(ssmVpa, SsmVerifyPackagesEvent.class);
- SsmUpgradePackagesAction ssmUpa = new SsmUpgradePackagesAction(); + SsmPackagesAction ssmUpa = new SsmUpgradePackagesAction(); MessageQueue.registerAction(ssmUpa, SsmUpgradePackagesEvent.class);
//Clone Errata into a channel diff --git a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ScheduleRemoteCommand.java b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ScheduleRemoteCommand.java index 11a0f64..8802a23 100644 --- a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ScheduleRemoteCommand.java +++ b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ScheduleRemoteCommand.java @@ -184,8 +184,8 @@ public class ScheduleRemoteCommand extends RhnAction { }
// scheduleScriptRun takes a list of servers - List servers = new ArrayList(); - servers.add(server); + List<Long> sids = new ArrayList<Long>(); + sids.add(server.getId());
ActionMessages msgs = new ActionMessages();
@@ -215,7 +215,7 @@ public class ScheduleRemoteCommand extends RhnAction { if (BEFORE.equals(runBefore)) { ScriptActionDetails sad = ActionManager.createScript(username, group, timeout, script); - ScriptRunAction sra = ActionManager.scheduleScriptRun(user, servers, + ScriptRunAction sra = ActionManager.scheduleScriptRun(user, sids, null, sad, earliest); List<Map<String, Long>> packs = getPackages(user, request, sessionSetLabel); int numPackages = packs.size(); @@ -231,7 +231,7 @@ public class ScheduleRemoteCommand extends RhnAction { PackageAction pa = schedulePackageAction(user, server, packs, mode, earliest); ScriptActionDetails sad = ActionManager.createScript(username, group, timeout, script); - ScriptRunAction sra = ActionManager.scheduleScriptRun(user, servers, + ScriptRunAction sra = ActionManager.scheduleScriptRun(user, sids, null, sad, earliest); sra.setPrerequisite(pa); ActionManager.storeAction(sra); diff --git a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageInstallationAction.java b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageInstallationAction.java index e4b8cd9..a071fef 100644 --- a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageInstallationAction.java +++ b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageInstallationAction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2012 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -15,18 +15,22 @@ package com.redhat.rhn.frontend.action.rhnpackage.ssm;
import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; import org.apache.struts.action.DynaActionForm; + import com.redhat.rhn.common.db.datasource.DataResult; -import com.redhat.rhn.common.localization.LocalizationService; import com.redhat.rhn.common.messaging.MessageQueue; import com.redhat.rhn.common.util.DatePicker; import com.redhat.rhn.domain.user.User; @@ -42,8 +46,8 @@ import com.redhat.rhn.frontend.taglibs.list.helper.Listable; import com.redhat.rhn.manager.system.SystemManager;
/** - * SSM action that handles prompting the user for when to install the package as well - * as creating the action when the user confirms the creation. + * SSM action that handles prompting the user for when to install the package as well as + * creating the action when the user confirms the creation. */ public class SchedulePackageInstallationAction extends RhnListAction implements Listable {
@@ -53,47 +57,59 @@ public class SchedulePackageInstallationAction extends RhnListAction implements HttpServletRequest request, HttpServletResponse response) throws Exception {
+ DynaActionForm f = (DynaActionForm) actionForm; RequestContext requestContext = new RequestContext(request);
- ListHelper helper = new ListHelper(this, request); - helper.setDataSetName(RequestContext.PAGE_LIST); - helper.execute(); + Map params = new HashMap(); + params.put(RequestContext.CID, requestContext.getRequiredParam(RequestContext.CID)); + params.put(RequestContext.MODE, + requestContext.getRequiredParamAsString(RequestContext.MODE));
- if (request.getParameter("dispatch") != null) { - if (requestContext.wasDispatched("installconfirm.jsp.confirm")) { + ListHelper lHelp = new ListHelper(this, request); + lHelp.setDataSetName(RequestContext.PAGE_LIST); + lHelp.execute();
- StrutsDelegate strutsDelegate = getStrutsDelegate(); + StrutsDelegate strutsDelegate = getStrutsDelegate();
+ if (request.getParameter(RequestContext.DISPATCH) != null) { + + String packagesDecl = request.getParameter("packagesDecl"); + + if (requestContext.wasDispatched("installconfirm.jsp.confirm")) { // Load data from the web components User user = requestContext.getLoggedInUser(); - Date earliest = getStrutsDelegate().readDatePicker( - (DynaActionForm) actionForm, "date", DatePicker.YEAR_RANGE_POSITIVE); + Date earliest = getStrutsDelegate() + .readDatePicker((DynaActionForm) actionForm, "date", + DatePicker.YEAR_RANGE_POSITIVE); Long cid = requestContext.getRequiredParam(RequestContext.CID); - - String packagesDecl = request.getParameter("packagesDecl"); - Set<String> data = SessionSetHelper.lookupAndBind(request, packagesDecl); - - // Remove the packages from session once we have the above handle on them + // Remove the packages from session once we have the above handle on + // them SessionSetHelper.obliterate(request, packagesDecl);
// Fire off the request on the message queue - SsmInstallPackagesEvent event = - new SsmInstallPackagesEvent(user.getId(), earliest, data, cid); + SsmInstallPackagesEvent event = new SsmInstallPackagesEvent(user.getId(), + earliest, data, cid); MessageQueue.publish(event);
ActionMessages msgs = new ActionMessages();
- // Check to determine to display single or plural confirmation message - int numPackages = data.size(); - LocalizationService l10n = LocalizationService.getInstance(); - msgs.add(ActionMessages.GLOBAL_MESSAGE, - new ActionMessage("ssm.package.install.message.packageinstalls")); + msgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + "ssm.package.install.message.packageinstalls")); strutsDelegate.saveMessages(request, msgs); - return actionMapping.findForward("confirm"); } - + else if (requestContext.wasDispatched("installconfirm.jsp.runremotecommand")) { + // Need to allow the user to specify a remote-cmd, either + // before or after the package-install + params.put("packagesDecl", packagesDecl); + DatePicker picker = getStrutsDelegate().prepopulateDatePicker(request, f, + "date", DatePicker.YEAR_RANGE_POSITIVE); + picker.writeToMap(params); + + return strutsDelegate.forwardParams(actionMapping.findForward("remote"), + params); + } }
// Determine number of packages for summary text to user @@ -104,11 +120,12 @@ public class SchedulePackageInstallationAction extends RhnListAction implements // Prepopulate the date picker DynaActionForm dynaForm = (DynaActionForm) actionForm; DatePicker picker = getStrutsDelegate().prepopulateDatePicker(request, dynaForm, - "date", DatePicker.YEAR_RANGE_POSITIVE); + "date", DatePicker.YEAR_RANGE_POSITIVE);
request.setAttribute("date", picker);
- return actionMapping.findForward(RhnHelper.DEFAULT_FORWARD); + return strutsDelegate.forwardParams( + actionMapping.findForward(RhnHelper.DEFAULT_FORWARD), params); }
/** {@inheritDoc} */ @@ -116,8 +133,8 @@ public class SchedulePackageInstallationAction extends RhnListAction implements Long cid = context.getRequiredParam(RequestContext.CID); User user = context.getLoggedInUser();
- DataResult dataResult = - SystemManager.systemsSubscribedToChannelInSet(cid, user, SetLabels.SYSTEM_LIST); + DataResult dataResult = SystemManager.systemsSubscribedToChannelInSet(cid, user, + SetLabels.SYSTEM_LIST);
return dataResult; } diff --git a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageRemoveAction.java b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageRemoveAction.java index 4dd0f38..abeb9f9 100644 --- a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageRemoveAction.java +++ b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageRemoveAction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2012 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -46,7 +46,9 @@ import org.apache.struts.action.ActionMessages; import org.apache.struts.action.DynaActionForm;
import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set;
import javax.servlet.http.HttpServletRequest; @@ -67,18 +69,33 @@ public class SchedulePackageRemoveAction extends RhnListAction implements Listab HttpServletResponse response) throws Exception {
RequestContext requestContext = new RequestContext(request); + DynaActionForm f = (DynaActionForm) actionForm;
ListHelper helper = new ListHelper(this, request); helper.setDataSetName(RequestContext.PAGE_LIST); helper.execute();
+ Map params = new HashMap(); + params.put(RequestContext.MODE, + requestContext.getRequiredParamAsString(RequestContext.MODE)); + if (request.getParameter("dispatch") != null) { + String packagesDecl = request.getParameter("packagesDecl"); if (requestContext.wasDispatched("installconfirm.jsp.confirm")) { return executePackageAction(actionMapping, actionForm, request, response); } + else if (requestContext.wasDispatched("removeconfirm.jsp.runremotecommand")) { + StrutsDelegate strutsDelegate = getStrutsDelegate(); + params.put("packagesDecl", packagesDecl); + DatePicker picker = getStrutsDelegate().prepopulateDatePicker(request, f, + "date", DatePicker.YEAR_RANGE_POSITIVE); + picker.writeToMap(params); + return strutsDelegate.forwardParams(actionMapping.findForward("remote"), + params); + } }
- // Prepopulate the date picker + // Pre-populate the date picker DynaActionForm dynaForm = (DynaActionForm) actionForm; DatePicker picker = getStrutsDelegate().prepopulateDatePicker(request, dynaForm, "date", DatePicker.YEAR_RANGE_POSITIVE); @@ -98,11 +115,11 @@ public class SchedulePackageRemoveAction extends RhnListAction implements Listab /** * Provide the data result * @param context The request context - * @param shorten whether to return a DataResult with the full ealborator + * @param shorten whether to return a DataResult with the full elaborator * or a shortened much faster ones * @return the List */ - public List getResult(RequestContext context, boolean shorten) { + public List<Map> getResult(RequestContext context, boolean shorten) { HttpServletRequest request = context.getRequest(); User user = context.getLoggedInUser();
@@ -127,7 +144,7 @@ public class SchedulePackageRemoveAction extends RhnListAction implements Listab
TagHelper.bindElaboratorTo("groupList", results.getElaborator(), request);
- return results; + return (List<Map>)results; }
/** @@ -153,8 +170,7 @@ public class SchedulePackageRemoveAction extends RhnListAction implements Listab "date", DatePicker.YEAR_RANGE_POSITIVE);
// Parse through all of the results - DataResult result = (DataResult) getResult(context, true); - result.elaborate(); + List<Map> result = getResult(context, true);
log.debug("Publishing schedule package remove event to message queue."); SsmRemovePackagesEvent event = new SsmRemovePackagesEvent(user.getId(), earliest, diff --git a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageUpgradeAction.java b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageUpgradeAction.java index fb11b85..34582bc 100644 --- a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageUpgradeAction.java +++ b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SchedulePackageUpgradeAction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2012 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -69,18 +69,33 @@ public class SchedulePackageUpgradeAction extends RhnAction implements Listable HttpServletResponse response) throws Exception {
RequestContext requestContext = new RequestContext(request); + DynaActionForm f = (DynaActionForm) actionForm;
ListHelper helper = new ListHelper(this, request); helper.setDataSetName(RequestContext.PAGE_LIST); helper.execute();
+ Map params = new HashMap(); + params.put(RequestContext.MODE, + requestContext.getRequiredParamAsString(RequestContext.MODE)); + if (request.getParameter("dispatch") != null) { + String packagesDecl = request.getParameter("packagesDecl"); if (requestContext.wasDispatched("installconfirm.jsp.confirm")) { return executePackageAction(actionMapping, actionForm, request, response); } + else if (requestContext.wasDispatched("upgradeconfirm.jsp.runremotecommand")) { + StrutsDelegate strutsDelegate = getStrutsDelegate(); + params.put("packagesDecl", packagesDecl); + DatePicker picker = getStrutsDelegate().prepopulateDatePicker(request, f, + "date", DatePicker.YEAR_RANGE_POSITIVE); + picker.writeToMap(params); + return strutsDelegate.forwardParams(actionMapping.findForward("remote"), + params); + } }
- // Prepopulate the date picker + // Pre-populate the date picker DynaActionForm dynaForm = (DynaActionForm) actionForm; DatePicker picker = getStrutsDelegate().prepopulateDatePicker(request, dynaForm, "date", DatePicker.YEAR_RANGE_POSITIVE); diff --git a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/ScheduleRemoteCommand.java b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/ScheduleRemoteCommand.java new file mode 100644 index 0000000..9676501 --- /dev/null +++ b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/ScheduleRemoteCommand.java @@ -0,0 +1,354 @@ +/** + * Copyright (c) 2009--2013 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.frontend.action.rhnpackage.ssm; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.struts.action.ActionErrors; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.apache.struts.action.DynaActionForm; + +import com.redhat.rhn.common.db.datasource.DataResult; +import com.redhat.rhn.common.localization.LocalizationService; +import com.redhat.rhn.common.messaging.EventMessage; +import com.redhat.rhn.common.messaging.MessageQueue; +import com.redhat.rhn.common.util.DatePicker; +import com.redhat.rhn.domain.action.script.ScriptActionDetails; +import com.redhat.rhn.domain.rhnpackage.PackageEvr; +import com.redhat.rhn.domain.rhnpackage.PackageEvrFactory; +import com.redhat.rhn.domain.rhnset.RhnSet; +import com.redhat.rhn.domain.rhnset.SetCleanup; +import com.redhat.rhn.domain.user.User; +import com.redhat.rhn.frontend.dto.PackageListItem; +import com.redhat.rhn.frontend.events.SsmInstallPackagesEvent; +import com.redhat.rhn.frontend.events.SsmRemovePackagesEvent; +import com.redhat.rhn.frontend.events.SsmUpgradePackagesEvent; +import com.redhat.rhn.frontend.struts.RequestContext; +import com.redhat.rhn.frontend.struts.RhnAction; +import com.redhat.rhn.frontend.struts.RhnHelper; +import com.redhat.rhn.frontend.struts.SessionSetHelper; +import com.redhat.rhn.frontend.struts.StrutsDelegate; +import com.redhat.rhn.frontend.taglibs.list.TagHelper; +import com.redhat.rhn.manager.action.ActionManager; +import com.redhat.rhn.manager.entitlement.EntitlementManager; +import com.redhat.rhn.manager.rhnset.RhnSetDecl; +import com.redhat.rhn.manager.rhnset.RhnSetManager; +import com.redhat.rhn.manager.ssm.SsmManager; +import com.redhat.rhn.manager.system.SystemManager; + +/** + * ScheduleRemoteCommand + * + * @version $Rev$ + */ +public class ScheduleRemoteCommand extends RhnAction { + public static final String BEFORE = "before"; + public static final String MODE_REMOVAL = "remove"; + public static final String MODE_UPGRADE = "upgrade"; + public static final String MODE_INSTALL = "install"; + + public static final String CAPABLE = "capable"; + public static final String ENTITLED = "entitled"; + + /** + * {@inheritDoc} + */ + public ActionForward execute(ActionMapping mapping, + ActionForm form, + HttpServletRequest request, + HttpServletResponse response) { + + StrutsDelegate strutsDelegate = getStrutsDelegate(); + + ActionForward forward = null; + DynaActionForm f = (DynaActionForm) form; + String mode = (String) f.get("mode"); + + RequestContext requestContext = new RequestContext(request); + Long cid = null; + if (MODE_INSTALL.equals(mode)) { + cid = requestContext.getRequiredParam("cid"); + } + User user = requestContext.getLoggedInUser(); + + Map reqMap = new HashMap(); + reqMap.putAll(request.getParameterMap()); + + if (!isSubmitted(f)) { + ActionErrors errs = checkAllowed(user); + if (!errs.isEmpty()) { + strutsDelegate.saveMessages(request, errs); + } + setup(request, f); + forward = strutsDelegate.forwardParams( + mapping.findForward(RhnHelper.DEFAULT_FORWARD), reqMap); + } + else { + ActionErrors errs = checkAllowed(user); + if (!errs.isEmpty()) { + strutsDelegate.saveMessages(request, errs); + forward = strutsDelegate.forwardParams( + mapping.findForward(RhnHelper.DEFAULT_FORWARD), reqMap); + } + else { + ActionMessages msgs = processForm(user, cid, f, request); + strutsDelegate.saveMessages(request, msgs); + forward = strutsDelegate.forwardParams(mapping.findForward("confirm"), + reqMap); + } + } + + return forward; + } + + private ActionErrors checkAllowed(User u) { + List<Long> notCapable = new ArrayList<Long>(); + List<Long> notEntitled = new ArrayList<Long>(); + + for (Long sid : SsmManager.listServerIds(u)) { + if (!SystemManager.clientCapable(sid, "script.run")) { + notCapable.add(sid); + } + + if (!SystemManager.hasEntitlement(sid, EntitlementManager.PROVISIONING)) { + notEntitled.add(sid); + } + } + + ActionErrors errs = new ActionErrors(); + if (!notCapable.isEmpty()) { + errs.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage( + "message.capability.missing", "script.run")); + } + if (!notEntitled.isEmpty()) { + errs.add(ActionErrors.GLOBAL_MESSAGE, + new ActionMessage("message.entitlement.missing", + EntitlementManager.PROVISIONING.getHumanReadableLabel())); + } + return errs; + } + + private ActionMessages processForm(User user, + Long cid, + DynaActionForm f, + HttpServletRequest request) { + + RequestContext ctxt = new RequestContext(request); + String runBefore = (String) f.get("run_script"); + String username = (String) f.get("username"); + String group = (String) f.get("group"); + Long timeout = (Long) f.get("timeout"); + String script = (String) f.get("script"); + String sessionSetLabel = (String) f.get("session_set_label"); + + String mode = (String) f.get("mode"); + + // The earliest time to perform the action. + Date earliest = getStrutsDelegate().readDatePicker(f, "date", + DatePicker.YEAR_RANGE_POSITIVE); + + ScriptActionDetails sad = ActionManager.createScript(username, group, timeout, + script); + boolean isBefore = (BEFORE.equals(runBefore)); + + ActionMessages msgs = new ActionMessages(); + + // Fire off the request on the message queue + EventMessage event; + if (MODE_INSTALL.equals(mode)) { + Set<String> pkgNames = SessionSetHelper.lookupAndBind(request, sessionSetLabel); + event = new SsmInstallPackagesEvent(user.getId(), earliest, pkgNames, cid, sad, + isBefore); + MessageQueue.publish(event); + SessionSetHelper.obliterate(request, sessionSetLabel); + + msgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + "ssm.package.install.message.packageinstalls")); + } + else if (MODE_UPGRADE.equals(mode)) { + List<Map> result = getUpgradeResult(ctxt, sessionSetLabel); + + Map<Long, List<Map<String, Long>>> sysPackageSet = + new HashMap<Long, List<Map<String, Long>>>(); + for (Map sys : result) { + Long sysId = (Long) sys.get("id"); + List<Map<String, Long>> pkgSet = new ArrayList<Map<String, Long>>(); + sysPackageSet.put(sysId, pkgSet); + for (Map pkg : (List<Map>) sys.get("elaborator0")) { + Map<String, Long> newPkg = new HashMap(); + newPkg.put("name_id", (Long) pkg.get("name_id")); + newPkg.put("evr_id", (Long) pkg.get("evr_id")); + newPkg.put("arch_id", (Long) pkg.get("arch_id")); + pkgSet.add(newPkg); + } + } + + event = new SsmUpgradePackagesEvent(user.getId(), earliest, sysPackageSet, sad, + isBefore); + + MessageQueue.publish(event); + SessionSetHelper.obliterate(request, sessionSetLabel); + RhnSetManager.deleteByLabel(user.getId(), + RhnSetDecl.SSM_UPGRADE_PACKAGES_LIST.getLabel()); + + msgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + "ssm.package.upgrade.message.packageupgrade")); + } + else if (MODE_REMOVAL.equals(mode)) { + List<Map> result = getRemoveResult(ctxt, sessionSetLabel); + + event = new SsmRemovePackagesEvent(user.getId(), earliest, result, sad, + isBefore); + + MessageQueue.publish(event); + SessionSetHelper.obliterate(request, sessionSetLabel); + RhnSetManager.deleteByLabel(user.getId(), + RhnSetDecl.SSM_REMOVE_PACKAGES_LIST.getLabel()); + + msgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + "ssm.package.remove.message.packageremovals")); + } + + return msgs; + } + + private void setup(HttpServletRequest request, DynaActionForm form) { + form.set("run_script", "before"); + form.set("username", "root"); + form.set("group", "root"); + form.set("timeout", new Long(600)); + form.set("script", "#!/bin/sh"); + form.set("mode", request.getParameter("mode")); + form.set("session_set_label", request.getParameter("packagesDecl")); + + Date date = getStrutsDelegate().readDatePicker(form, "date", + DatePicker.YEAR_RANGE_POSITIVE); + + request.setAttribute("scheduledDate", + LocalizationService.getInstance().formatDate(date)); + } + + private List getUpgradeResult(RequestContext context, String setLabel) { + + HttpServletRequest request = context.getRequest(); + User user = context.getLoggedInUser(); + + // Stuff packages into an RhnSet to be used in the query + if (setLabel != null) { + Set<String> data = SessionSetHelper.lookupAndBind(request, setLabel); + + // bz465892 - As the selected packages are parsed, remove duplicates + // keeping the highest EVR + Map<String, PackageListItem> packageNameIdsToItems = + new HashMap<String, PackageListItem>(data.size()); + + for (String idCombo : data) { + PackageListItem item = PackageListItem.parse(idCombo); + + PackageListItem existing = packageNameIdsToItems.get(item.getIdOne() + "|" + + item.getIdThree()); + if (existing != null) { + String[] existingParts = splitEvr(existing.getNvre()); + String[] itemParts = splitEvr(item.getNvre()); + + PackageEvr existingEvr = PackageEvrFactory.lookupOrCreatePackageEvr( + existingParts[0], existingParts[1], existingParts[2]); + + PackageEvr itemEvr = PackageEvrFactory.lookupOrCreatePackageEvr( + itemParts[0], itemParts[1], itemParts[2]); + + if (existingEvr.compareTo(itemEvr) < 0) { + packageNameIdsToItems.put( + item.getIdOne() + "|" + item.getIdThree(), item); + } + } + else { + packageNameIdsToItems.put(item.getIdOne() + "|" + item.getIdThree(), + item); + } + } + + RhnSet packageSet = RhnSetManager.createSet(user.getId(), + RhnSetDecl.SSM_UPGRADE_PACKAGES_LIST.getLabel(), SetCleanup.NOOP); + + for (PackageListItem item : packageNameIdsToItems.values()) { + packageSet.addElement(item.getIdOne(), item.getIdTwo(), item.getIdThree()); + } + + RhnSetManager.store(packageSet); + } + + DataResult results = SystemManager.ssmSystemPackagesToUpgrade(user, + RhnSetDecl.SSM_UPGRADE_PACKAGES_LIST.getLabel()); + + TagHelper.bindElaboratorTo("groupList", results.getElaborator(), request); + results.elaborate(); + + return results; + } + + private String[] splitEvr(String evr) { + String[] values = StringUtils.split(evr, "-"); + for (int i = 0; i < values.length; i++) { + if ("null".equals(values[i])) { + values[i] = null; + } + } + return values; + } + + private List getRemoveResult(RequestContext context, String setLabel) { + HttpServletRequest request = context.getRequest(); + User user = context.getLoggedInUser(); + + // Stuff packages into an RhnSet to be used in the query + String packagesDecl = (String) request.getAttribute("packagesDecl"); + if (packagesDecl != null) { + Set<String> data = SessionSetHelper.lookupAndBind(request, packagesDecl); + + RhnSet packageSet = RhnSetManager.createSet(user.getId(), + RhnSetDecl.SSM_REMOVE_PACKAGES_LIST.getLabel(), SetCleanup.NOOP); + + for (String idCombo : data) { + PackageListItem item = PackageListItem.parse(idCombo); + packageSet.addElement(item.getIdOne(), item.getIdTwo(), item.getIdThree()); + } + + RhnSetManager.store(packageSet); + } + + DataResult results = SystemManager.ssmSystemPackagesToRemove(user, + RhnSetDecl.SSM_REMOVE_PACKAGES_LIST.getLabel(), true); + + TagHelper.bindElaboratorTo("groupList", results.getElaborator(), request); + results.elaborate(); + + return results; + } + +} diff --git a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectInstallationPackagesAction.java b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectInstallationPackagesAction.java index 495c037..b8ac8c1 100644 --- a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectInstallationPackagesAction.java +++ b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectInstallationPackagesAction.java @@ -36,7 +36,7 @@ import javax.servlet.http.HttpServletResponse; /** * SSM action for selecting the packages to install. Package list is determined by the * first step in the flow where the channel is selected. - * + * * @version $Revision$ */ public class SelectInstallationPackagesAction extends RhnAction implements Listable { @@ -45,33 +45,32 @@ public class SelectInstallationPackagesAction extends RhnAction implements Lista public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, - HttpServletResponse response) - throws Exception { + HttpServletResponse response) throws Exception {
RequestContext context = new RequestContext(request); Map params = new HashMap(); params.put(RequestContext.CID, context.getRequiredParam(RequestContext.CID)); + params.put("mode", "install"); ListSessionSetHelper helper = new ListSessionSetHelper(this, request, params); helper.setDataSetName(RequestContext.PAGE_LIST); helper.execute();
+ StrutsDelegate strutsDelegate = getStrutsDelegate(); + if (helper.isDispatched()) { request.setAttribute("packagesDecl", helper.getDecl()); - return actionMapping.findForward("confirm"); + return strutsDelegate.forwardParams(actionMapping.findForward("confirm"), + params); }
- Map forwardParams = new HashMap(); - forwardParams.put(RequestContext.CID, context.getRequiredParam(RequestContext.CID)); - StrutsDelegate strutsDelegate = getStrutsDelegate(); - return strutsDelegate.forwardParams( - actionMapping.findForward(RhnHelper.DEFAULT_FORWARD), forwardParams); + actionMapping.findForward(RhnHelper.DEFAULT_FORWARD), params); }
/** {@inheritDoc} */ public List getResult(RequestContext context) { - Long cid = context.getRequiredParam(RequestContext.CID); - return ChannelManager.latestPackagesInChannel(cid); - } + Long cid = context.getRequiredParam(RequestContext.CID); + return ChannelManager.latestPackagesInChannel(cid); + }
} diff --git a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectRemovePackagesAction.java b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectRemovePackagesAction.java index da019c8..2977900 100644 --- a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectRemovePackagesAction.java +++ b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectRemovePackagesAction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2012 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -50,6 +50,7 @@ public class SelectRemovePackagesAction extends RhnAction implements Listable { request.setAttribute(ListTagHelper.PARENT_URL, request.getRequestURI());
Map params = new HashMap(); + params.put("mode", "remove");
ListSessionSetHelper helper = new ListSessionSetHelper(this, request, params); helper.setDataSetName(RequestContext.PAGE_LIST); diff --git a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectUpgradePackagesAction.java b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectUpgradePackagesAction.java index 2bed9dc..d731b94 100644 --- a/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectUpgradePackagesAction.java +++ b/java/code/src/com/redhat/rhn/frontend/action/rhnpackage/ssm/SelectUpgradePackagesAction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2012 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -50,6 +50,7 @@ public class SelectUpgradePackagesAction extends RhnAction implements Listable { request.setAttribute(ListTagHelper.PARENT_URL, request.getRequestURI());
Map params = new HashMap(); + params.put("mode", "upgrade");
ListSessionSetHelper helper = new ListSessionSetHelper(this, request, params); helper.setDataSetName(RequestContext.PAGE_LIST); diff --git a/java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesAction.java b/java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesAction.java index 6b48faf..a9c4c54 100644 --- a/java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesAction.java +++ b/java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesAction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2010 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -14,20 +14,6 @@ */ package com.redhat.rhn.frontend.events;
-import com.redhat.rhn.common.messaging.EventMessage; -import com.redhat.rhn.domain.user.User; -import com.redhat.rhn.domain.user.UserFactory; -import com.redhat.rhn.frontend.action.SetLabels; -import com.redhat.rhn.frontend.dto.EssentialServerDto; -import com.redhat.rhn.frontend.dto.PackageListItem; -import com.redhat.rhn.manager.action.ActionManager; -import com.redhat.rhn.manager.rhnset.RhnSetDecl; -import com.redhat.rhn.manager.ssm.SsmOperationManager; -import com.redhat.rhn.manager.system.SystemManager; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import java.util.ArrayList; import java.util.Date; import java.util.LinkedList; @@ -35,68 +21,60 @@ import java.util.List; import java.util.Map; import java.util.Set;
+import com.redhat.rhn.domain.action.Action; +import com.redhat.rhn.domain.user.User; +import com.redhat.rhn.frontend.action.SetLabels; +import com.redhat.rhn.frontend.dto.EssentialServerDto; +import com.redhat.rhn.frontend.dto.PackageListItem; +import com.redhat.rhn.manager.action.ActionManager; +import com.redhat.rhn.manager.system.SystemManager; + /** * Schedules package installations on systems in the SSM. */ -public class SsmInstallPackagesAction extends AbstractDatabaseAction { - - private final Log log = LogFactory.getLog(this.getClass()); - - protected void doExecute(EventMessage msg) { - SsmInstallPackagesEvent event = (SsmInstallPackagesEvent) msg; +public class SsmInstallPackagesAction extends SsmPackagesAction {
- User user = UserFactory.lookupById(event.getUserId()); + protected String getOperationName() { + return "ssm.package.install.operationname"; + } + + protected List<Long> getAffectedServers(SsmPackageEvent event, User u) { + SsmInstallPackagesEvent sipe = (SsmInstallPackagesEvent) event; + Long channelId = sipe.getChannelId();
- // Log the action has been created - long operationId = - SsmOperationManager.createOperation(user, - "ssm.package.install.operationname", RhnSetDecl.SYSTEMS.getLabel()); + List<EssentialServerDto> servers = SystemManager.systemsSubscribedToChannelInSet( + channelId, u, SetLabels.SYSTEM_LIST);
- try { - scheduleInstalls(event, user); - } - catch (Exception e) { - log.error("Error scheduling package installations for event " + event, e); - } - finally { - // This should stay in the finally block so the operation is - // not perpetually left in an in progress state - SsmOperationManager.completeOperation(user, operationId); + // Create one action for all servers to which the packages are installed + List<Long> serverIds = new LinkedList<Long>(); + for (EssentialServerDto dto : servers) { + serverIds.add(dto.getId()); } + return serverIds; }
- private void scheduleInstalls(SsmInstallPackagesEvent event, User user) { - - log.debug("Scheduling package installations."); - Date earliest = event.getEarliest(); - Set<String> data = event.getPackages(); - Long channelId = event.getChannelId(); - - List<EssentialServerDto> servers = - SystemManager.systemsSubscribedToChannelInSet(channelId, user, - SetLabels.SYSTEM_LIST); + protected List<Action> doSchedule(SsmPackageEvent event, + User user, + List<Long> sids, + Date earliest) { + SsmInstallPackagesEvent sipe = (SsmInstallPackagesEvent) event;
+ Set<String> data = sipe.getPackages(); // Convert the package list to domain objects - List<PackageListItem> packageListItems = - new ArrayList<PackageListItem>(data.size()); + List<PackageListItem> packageListItems = + new ArrayList<PackageListItem>(data.size()); for (String key : data) { packageListItems.add(PackageListItem.parse(key)); }
// Convert to list of maps - List<Map<String, Long>> packageListData = - PackageListItem.toKeyMaps(packageListItems); - - // Create one action for all servers to which the packages are installed - List<Long> serverIds = new LinkedList<Long>(); - for (EssentialServerDto dto : servers) { - serverIds.add(dto.getId()); - } - - log.debug("Scheduling actions."); - ActionManager.schedulePackageInstall(user, serverIds, - packageListData, earliest); - log.debug("Done scheduling package installations."); + List<Map<String, Long>> packageListData = PackageListItem + .toKeyMaps(packageListItems);
+ List<Action> pkgActions = ActionManager.schedulePackageInstall(user, sids, + packageListData, earliest); + + return pkgActions; } + } diff --git a/java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesEvent.java b/java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesEvent.java index 1f446b1..1316949 100644 --- a/java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesEvent.java +++ b/java/code/src/com/redhat/rhn/frontend/events/SsmInstallPackagesEvent.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2010 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -16,37 +16,38 @@ package com.redhat.rhn.frontend.events;
import java.util.Date; import java.util.Set; -import com.redhat.rhn.common.messaging.EventMessage; + +import com.redhat.rhn.domain.action.script.ScriptActionDetails;
/** - * Event fired to carry the information necessary to schedule package installations - * on systems in the SSM. + * Event fired to carry the information necessary to schedule package installations on + * systems in the SSM. */ -public class SsmInstallPackagesEvent implements EventMessage { +public class SsmInstallPackagesEvent extends SsmPackageEvent {
- private Long userId; - private Date earliest; - private Set<String> packages; - private Long channelId; + protected Set<String> packages; + protected Long channelId;
/** * Creates a new event to install a set of packages on systems in the SSM. - * - * @param userIdIn user making the changes; cannot be <code>null</code> - * @param earliestIn earliest time to perform the installation; - * can be <code>null</code> - * @param packagesIn set of package IDs being installed; cannot be <code>null</code> - * @param channelIdIn identifies the channel the packages are installed from; - * cannot be <code>null</code> + * + * @param userIdIn user making the changes; cannot be <code>null</code> + * @param earliestIn earliest time to perform the installation; can be + * <code>null</code> + * @param packagesIn set of package IDs being installed; cannot be <code>null</code> + * @param channelIdIn identifies the channel the packages are installed from; cannot + * be <code>null</code> + * @param detailsIn optional remote-command to execute before or after the install + * @param beforeIn optional boolean - true if details should be executed BEFORE the + * install, false if AFTER */ public SsmInstallPackagesEvent(Long userIdIn, - Date earliestIn, - Set<String> packagesIn, - Long channelIdIn) { - if (userIdIn == null) { - throw new IllegalArgumentException("userIdIn cannot be null"); - } - + Date earliestIn, + Set<String> packagesIn, + Long channelIdIn, + ScriptActionDetails detailsIn, + boolean beforeIn) { + super(userIdIn, earliestIn, detailsIn, beforeIn); if (packagesIn == null) { throw new IllegalArgumentException("packagesIn cannot be null"); } @@ -54,26 +55,25 @@ public class SsmInstallPackagesEvent implements EventMessage { if (channelIdIn == null) { throw new IllegalArgumentException("channelIdIn cannot be null"); } - - - this.userId = userIdIn; - this.earliest = earliestIn; this.packages = packagesIn; this.channelId = channelIdIn; }
/** - * @return will not be <code>null</code> - */ - public Long getUserId() { - return userId; - } - - /** - * @return may be <code>null</code> + * Creates a new event to install a set of packages on systems in the SSM. + * + * @param userIdIn user making the changes; cannot be <code>null</code> + * @param earliestIn earliest time to perform the installation; can be + * <code>null</code> + * @param packagesIn set of package IDs being installed; cannot be <code>null</code> + * @param channelIdIn identifies the channel the packages are installed from; cannot + * be <code>null</code> */ - public Date getEarliest() { - return earliest; + public SsmInstallPackagesEvent(Long userIdIn, + Date earliestIn, + Set<String> packagesIn, + Long channelIdIn) { + this(userIdIn, earliestIn, packagesIn, channelIdIn, null, false); }
/** @@ -91,13 +91,8 @@ public class SsmInstallPackagesEvent implements EventMessage { }
/** {@inheritDoc} */ - public String toText() { - return toString(); - } - - /** {@inheritDoc} */ public String toString() { - return "SsmPackageInstallEvent[User: " + userId + ", Package Count: " + - packages.size() + ", Channel ID: " + channelId + "]"; + return "SsmInstallPackagesEvent [" + super.toString() + ", numPkgs=" + + packages.size() + ", " + "channelId=" + channelId + "]"; } } diff --git a/java/code/src/com/redhat/rhn/frontend/events/SsmPackageEvent.java b/java/code/src/com/redhat/rhn/frontend/events/SsmPackageEvent.java new file mode 100644 index 0000000..8da985d --- /dev/null +++ b/java/code/src/com/redhat/rhn/frontend/events/SsmPackageEvent.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2009--2013 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.frontend.events; + +import java.util.Date; + +import com.redhat.rhn.common.messaging.EventMessage; +import com.redhat.rhn.domain.action.script.ScriptActionDetails; + +/** + * Base for SSM package install/update/remove actions. Holds the data shared between the + * three paths. + * + * @author ggainey + * + */ +public abstract class SsmPackageEvent implements EventMessage { + + protected Long userId; + protected Date earliest; + protected ScriptActionDetails scriptDetails; + protected boolean before; + + /** + * Creates a new event to install a set of packages on systems in the SSM. + * + * @param userIdIn user making the changes; cannot be <code>null</code> + * @param earliestIn earliest time to perform the installation; can be + * <code>null</code> + * @param detailsIn optional remote-command to execute before or after the install + * @param beforeIn optional boolean - true if details should be executed BEFORE the + * install, false if AFTER + */ + public SsmPackageEvent(Long userIdIn, + Date earliestIn, + ScriptActionDetails detailsIn, + boolean beforeIn) { + + if (userIdIn == null) { + throw new IllegalArgumentException("userIdIn cannot be null"); + } + + this.userId = userIdIn; + this.earliest = earliestIn; + this.scriptDetails = detailsIn; + this.before = beforeIn; + } + + /** + * @return will not be <code>null</code> + */ + public Long getUserId() { + return userId; + } + + /** + * @return may be <code>null</code> + */ + public Date getEarliest() { + return earliest; + } + + /** + * @return may be <code>null</code> + */ + public ScriptActionDetails getScriptDetails() { + return scriptDetails; + } + + /** + * @return true if getScriptDetails() should run BEFORE package-install, FALSE + * otherwise + */ + public boolean isBefore() { + return before; + } + + /** {@inheritDoc} */ + public String toString() { + return "SsmPackageEvent[userId=" + userId + ", " + + (earliest != null ? "earliest=" + earliest + ", " : "") + + (scriptDetails != null ? "scriptDetails=" + scriptDetails + ", " : "") + + "before=" + before + "]"; + } + + /** {@inheritDoc} */ + public String toText() { + return toString(); + } + +} diff --git a/java/code/src/com/redhat/rhn/frontend/events/SsmPackagesAction.java b/java/code/src/com/redhat/rhn/frontend/events/SsmPackagesAction.java new file mode 100644 index 0000000..069edf2 --- /dev/null +++ b/java/code/src/com/redhat/rhn/frontend/events/SsmPackagesAction.java @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2009--2013 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.frontend.events; + +import java.util.Date; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.redhat.rhn.common.messaging.EventMessage; +import com.redhat.rhn.domain.action.Action; +import com.redhat.rhn.domain.action.script.ScriptActionDetails; +import com.redhat.rhn.domain.action.script.ScriptRunAction; +import com.redhat.rhn.domain.user.User; +import com.redhat.rhn.domain.user.UserFactory; +import com.redhat.rhn.manager.action.ActionManager; +import com.redhat.rhn.manager.rhnset.RhnSetDecl; +import com.redhat.rhn.manager.ssm.SsmOperationManager; + +/** + * Base functionality for responding to SSM package install/update/remove. + * Handles ordering if a remote-cmd has been specified. Subclasses are responsible + * for describing the affected servers, and the actual work of scheduling action(s) + * + * @author ggainey + * + */ +public abstract class SsmPackagesAction extends AbstractDatabaseAction { + + private final Log log = LogFactory.getLog(this.getClass()); + + protected void doExecute(EventMessage msg) { + SsmPackageEvent event = (SsmPackageEvent) msg; + + User user = UserFactory.lookupById(event.getUserId()); + + /* + * Comment below applies to more than just SsmPackageUpgrade. Moving here into the + * (new) base-class for all actions, since it applies generally - there are often + * systems in RhnSet.SYSTEM to which an Ssm action WILL NOT apply, since SSM + * allows for heterogeneous sets of systems -- GRG 2013-APR-3 + */ + /* + * The following isn't 100% accurate. All systems in the SSM are associated with + * the operation, however only systems on which the package already exists (since + * this is an upgrade) will actually have events scheduled. + * + * The problem is that the list of servers to which the package upgrades apply is + * never stored in an RhnSet, which is used to make the impact of this call + * minimal. The correct list is showed to the user before selecting confirm, so + * the only potential issue is in viewing the SSM task log after the user has + * confirmed the operation. Again, the events themselves are correctly scheduled + * on only the systems to which they apply. + * + * For now, this small potential for logging inaccuracy is acceptable given the + * proxmity of this fix to the Satellite 5.3 release (as opposed to omitting the + * server association to the task entirely). + * + * jdobies, Aug 12, 2009 + */ + + long operationId = SsmOperationManager.createOperation(user, + getOperationName(), RhnSetDecl.SYSTEMS.getLabel()); + + // Explicitly call handle transactions here so the operation creation above + // is persisted before the potentially long running logic below + //handleTransactions(true); + + try { + long actionStart = System.currentTimeMillis(); + + scheduleAction(event, user); + + if (log.isDebugEnabled()) { + log.debug("Time to schedule all actions: " + + (System.currentTimeMillis() - actionStart)); + } + } + catch (Exception e) { + log.error("Error scheduling package installations for event " + event, e); + } + finally { + // This should stay in the finally block so the operation is + // not perpetually left in an in progress state + SsmOperationManager.completeOperation(user, operationId); + } + } + + protected void scheduleAction(SsmPackageEvent event, User user) { + + log.debug("Scheduling package actions."); + Date earliest = event.getEarliest(); + + List<Long> serverIds = getAffectedServers(event, user); + + log.debug("Scheduling actions."); + // If we have a remote-cmd, have to correctly order it and the package action(s) + if (event.getScriptDetails() != null) { + ScriptActionDetails sad = event.getScriptDetails(); + if (event.isBefore()) { + log.debug("Scheduling remote-action BEFORE."); + + ScriptRunAction sra = ActionManager.scheduleScriptRun(user, serverIds, + null, sad, earliest); + ActionManager.storeAction(sra); + + List<Action> pkgActions = doSchedule(event, user, serverIds, earliest); + + // Might be more than one action from schedPkgActions + Action prevAction = sra; + for (Action a : pkgActions) { + a.setPrerequisite(prevAction); + ActionManager.storeAction(a); + prevAction = a; + } + + } + else { + log.debug("Scheduling remote-action AFTER."); + + List<Action> pkgActions = doSchedule(event, user, serverIds, earliest); + ScriptRunAction sra = ActionManager.scheduleScriptRun(user, serverIds, + null, sad, earliest); + + // Might be more than one action from schedPkgActions + Action prevAction = null; + for (Action a : pkgActions) { + if (prevAction != null) { + a.setPrerequisite(prevAction); + } + ActionManager.storeAction(a); + prevAction = a; + } + + sra.setPrerequisite(prevAction); + ActionManager.storeAction(sra); + } + } + else { // No remote-script to schedule + doSchedule(event, user, serverIds, earliest); + } + log.debug("Done scheduling package actions."); + + } + + protected abstract String getOperationName(); + + protected abstract List<Long> getAffectedServers(SsmPackageEvent event, User u); + + protected abstract List<Action> doSchedule(SsmPackageEvent event, + User user, + List<Long> sids, + Date earliest); + +} diff --git a/java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesAction.java b/java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesAction.java index eda7efa..577c6a9 100644 --- a/java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesAction.java +++ b/java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesAction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2010 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -14,119 +14,104 @@ */ package com.redhat.rhn.frontend.events;
-import com.redhat.rhn.common.db.datasource.DataResult; -import com.redhat.rhn.common.messaging.EventMessage; -import com.redhat.rhn.domain.user.User; -import com.redhat.rhn.domain.user.UserFactory; -import com.redhat.rhn.frontend.dto.PackageListItem; -import com.redhat.rhn.manager.action.ActionManager; -import com.redhat.rhn.manager.rhnset.RhnSetDecl; -import com.redhat.rhn.manager.ssm.SsmOperationManager; - -import org.apache.log4j.Logger; - import java.util.ArrayList; import java.util.Date; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set;
+import org.apache.log4j.Logger; + +import com.redhat.rhn.domain.action.Action; +import com.redhat.rhn.domain.user.User; +import com.redhat.rhn.frontend.dto.PackageListItem; +import com.redhat.rhn.manager.action.ActionManager; + /** * Handles removing packages from servers in the SSM. - * + * * @see com.redhat.rhn.frontend.events.SsmRemovePackagesEvent */ -public class SsmRemovePackagesAction extends AbstractDatabaseAction { +public class SsmRemovePackagesAction extends SsmPackagesAction { private static Logger log = Logger.getLogger(SsmRemovePackagesAction.class);
- /** {@inheritDoc} */ - protected void doExecute(EventMessage msg) { - log.debug("Executing package removals."); - - SsmRemovePackagesEvent event = (SsmRemovePackagesEvent) msg; - User user = UserFactory.lookupById(event.getUserId()); - - long operationId = SsmOperationManager.createOperation(user, - "ssm.package.remove.operationname", RhnSetDecl.SYSTEMS.getLabel()); + protected String getOperationName() { + return "ssm.package.remove.operationname"; + }
- try { - scheduleDeletes(event, user); - } - catch (Exception e) { - log.error("Error scheduling package deletes for event: " + event, e); - } - finally { - // This should stay in the finally block so the operation is - // not perpetually left in an in progress state - SsmOperationManager.completeOperation(user, operationId); + protected List<Long> getAffectedServers(SsmPackageEvent event, User u) { + SsmRemovePackagesEvent srpe = (SsmRemovePackagesEvent) event; + List<Long> sids = new ArrayList<Long>(); + List<Map> result = srpe.getResult(); + for (Map data : result) { + Long sid = (Long) data.get("id"); + sids.add(sid); } + return sids; }
- private void scheduleDeletes(SsmRemovePackagesEvent event, User user) { - - DataResult result = event.getResult(); - Date earliest = event.getEarliest(); - - /* 443500 - The following was changed to be able to stuff all of the package - removals into a single action. The schedule package removal page will display - a fine grained mapping of server to package removed (taking into account to - only show packages that exist on the server). - - However, there is no issue in requesting a client delete a package it doesn't - have. So when we create the action, populate it with all packages and for - every server to which any package removal applies. This will let us keep all - of the removals coupled under a single scheduled action and won't cause an - issue on the client when the scheduled removals are picked up. - - jdobies, Apr 8, 2009 - */ - - // The package collection is a set to prevent duplciates when keeping a running + protected List<Action> doSchedule(SsmPackageEvent event, + User user, + List<Long> sids, + Date earliest) { + + SsmRemovePackagesEvent srpe = (SsmRemovePackagesEvent) event; + + List<Map> result = srpe.getResult(); + + /* + * 443500 - The following was changed to be able to stuff all of the package + * removals into a single action. The schedule package removal page will display a + * fine grained mapping of server to package removed (taking into account to only + * show packages that exist on the server). + * + * However, there is no issue in requesting a client delete a package it doesn't + * have. So when we create the action, populate it with all packages and for every + * server to which any package removal applies. This will let us keep all of the + * removals coupled under a single scheduled action and won't cause an issue on + * the client when the scheduled removals are picked up. + * + * jdobies, Apr 8, 2009 + */ + + // The package collection is a set to prevent duplicates when keeping a running // total of all packages selected Set<PackageListItem> allPackages = new HashSet<PackageListItem>();
- Set<Long> allServerIds = new HashSet<Long>();
// Iterate the data, which is essentially each unique package/server combination // to remove. Note that this is only for servers that we have marked as having the // package installed. log.debug("Iterating data."); - for (Iterator it = result.iterator(); it.hasNext();) { - - // Add action for each package found in the elaborator - Map data = (Map) it.next();
+ // Add action for each package found in the elaborator + for (Map data : result) { // Load the server Long sid = (Long) data.get("id"); allServerIds.add(sid);
// Get the packages out of the elaborator - List elabList = (List) data.get("elaborator0"); - - for (Iterator elabIt = elabList.iterator(); elabIt.hasNext();) { - Map elabData = (Map) elabIt.next(); - String idCombo = (String) elabData.get("id_combo"); + List<Map> elabList = (List<Map>) data.get("elaborator0"); + for (Map elabMap : elabList) { + String idCombo = (String) elabMap.get("id_combo"); PackageListItem item = PackageListItem.parse(idCombo); allPackages.add(item); } }
- log.debug("Converting data to maps."); - List<PackageListItem> allPackagesList = - new ArrayList<PackageListItem>(allPackages); - List<Map<String, Long>> packageListData = - PackageListItem.toKeyMaps(allPackagesList); + List<PackageListItem> allPackagesList = new ArrayList<PackageListItem>(allPackages); + List<Map<String, Long>> packageListData = PackageListItem + .toKeyMaps(allPackagesList);
log.debug("Scheduling package removals."); - ActionManager.schedulePackageRemoval(user, allServerIds, - packageListData, earliest); + List<Action> actions = ActionManager.schedulePackageRemoval(user, allServerIds, + packageListData, earliest);
log.debug("Done."); + return actions; }
} - diff --git a/java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesEvent.java b/java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesEvent.java index 1116731..dfde791 100644 --- a/java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesEvent.java +++ b/java/code/src/com/redhat/rhn/frontend/events/SsmRemovePackagesEvent.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2010 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -14,11 +14,11 @@ */ package com.redhat.rhn.frontend.events;
-import com.redhat.rhn.common.db.datasource.DataResult; - -import com.redhat.rhn.common.messaging.EventMessage; - import java.util.Date; +import java.util.List; +import java.util.Map; + +import com.redhat.rhn.domain.action.script.ScriptActionDetails;
/** * Event fired to carry the information necessary to remove packages from servers in the @@ -27,51 +27,43 @@ import java.util.Date; * @see com.redhat.rhn.frontend.events.SsmRemovePackagesAction * @version $Revision$ */ -public class SsmRemovePackagesEvent implements EventMessage { +public class SsmRemovePackagesEvent extends SsmPackageEvent {
- private Long userId; - private Date earliest; - private DataResult result; + private List<Map> result;
/** * Creates a new SSM remove packages event. * - * @param userIdIn ID of user scheduling this action. - * @param earliestIn Earliest data action can be picked up. - * @param resultIn Complex map of which packages we're removing from which servers. + * @param userIdIn ID of user scheduling this action. + * @param earliestIn Earliest data action can be picked up. + * @param resultIn Complex map of which packages we're removing from which servers. + * @param detailsIn optional remote-command to execute before or after the install + * @param beforeIn optional boolean - true if details should be executed BEFORE the + * install, false if AFTER */ - public SsmRemovePackagesEvent(Long userIdIn, Date earliestIn, DataResult resultIn) { - userId = userIdIn; - earliest = earliestIn; + public SsmRemovePackagesEvent(Long userIdIn, + Date earliestIn, + List<Map> resultIn, + ScriptActionDetails detailsIn, + boolean beforeIn) { + super(userIdIn, earliestIn, detailsIn, beforeIn); result = resultIn; }
- /** {@inheritDoc} */ - public String toText() { - return toString(); - } - - /** {@inheritDoc} */ - public String toString() { - return "SsmRemovePackagesEvent[User ID: " + userId + "]"; - } - /** - * Gets the user for this instance. + * Creates a new SSM remove packages event. * - * @return The user. + * @param userIdIn ID of user scheduling this action. + * @param earliestIn Earliest data action can be picked up. + * @param resultIn Complex map of which packages we're removing from which servers. */ - public Long getUserId() { - return this.userId; + public SsmRemovePackagesEvent(Long userIdIn, Date earliestIn, List<Map> resultIn) { + this(userIdIn, earliestIn, resultIn, null, false); }
- /** - * Gets the earliest for this instance. - * - * @return The earliest. - */ - public Date getEarliest() { - return this.earliest; + /** {@inheritDoc} */ + public String toString() { + return "SsmRemovePackagesEvent[" + super.toString() + "]"; }
/** @@ -79,7 +71,7 @@ public class SsmRemovePackagesEvent implements EventMessage { * * @return The result. */ - public DataResult getResult() { + public List<Map> getResult() { return this.result; }
diff --git a/java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesAction.java b/java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesAction.java index ac46ef2..c13a34f 100644 --- a/java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesAction.java +++ b/java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesAction.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2010 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -14,89 +14,43 @@ */ package com.redhat.rhn.frontend.events;
-import com.redhat.rhn.common.messaging.EventMessage; -import com.redhat.rhn.domain.user.User; -import com.redhat.rhn.domain.user.UserFactory; -import com.redhat.rhn.manager.action.ActionManager; -import com.redhat.rhn.manager.rhnset.RhnSetDecl; -import com.redhat.rhn.manager.ssm.SsmOperationManager; - -import org.apache.log4j.Logger; - +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map;
+import com.redhat.rhn.domain.action.Action; +import com.redhat.rhn.domain.user.User; +import com.redhat.rhn.manager.action.ActionManager; + /** * Handles removing packages from servers in the SSM. - * + * * @see com.redhat.rhn.frontend.events.SsmUpgradePackagesEvent */ -public class SsmUpgradePackagesAction extends AbstractDatabaseAction { - - private static Logger log = Logger.getLogger(SsmUpgradePackagesAction.class); - - /** {@inheritDoc} */ - protected void doExecute(EventMessage msg) { - log.debug("Executing package upgrades."); - - SsmUpgradePackagesEvent event = (SsmUpgradePackagesEvent) msg; - User user = UserFactory.lookupById(event.getUserId()); - - /* The following isn't 100% accurate. All systems in the SSM are associated - with the operation, however only systems on which the package already exists - (since this is an upgrade) will actually have events scheduled. +public class SsmUpgradePackagesAction extends SsmPackagesAction {
- The problem is that the list of servers to which the package upgrades apply - is never stored in an RhnSet, which is used to make the impact of this call - minimal. The correct list is showed to the user before selecting confirm, - so the only potential issue is in viewing the SSM task log after the user - has confirmed the operation. Again, the events themselves are correctly - scheduled on only the systems to which they apply. - - For now, this small potential for logging inaccuracy is acceptable given the - proxmity of this fix to the Satellite 5.3 release (as opposed to omitting - the server association to the task entirely). - - jdobies, Aug 12, 2009 - */ - - - long operationId = SsmOperationManager.createOperation(user, - "ssm.package.upgrade.operationname", RhnSetDecl.SYSTEMS.getLabel()); - - // Explicitly call handle transactions here so the operation creation above - // is persisted before the potentially long running logic below - handleTransactions(true); - - try { - scheduleUpgrades(user, event); - } - catch (Exception e) { - log.error("Error while scheduling package upgrades for event: " + event, e); - } - finally { - - SsmOperationManager.completeOperation(user, operationId); - } - - log.debug("Done."); + protected String getOperationName() { + return "ssm.package.upgrade.operationname"; + } + + protected List<Long> getAffectedServers(SsmPackageEvent event, User u) { + SsmUpgradePackagesEvent supe = (SsmUpgradePackagesEvent) event; + List<Long> sids = new ArrayList<Long>(); + sids.addAll(supe.getSysPackageSet().keySet()); + return sids; }
- private void scheduleUpgrades(User user, SsmUpgradePackagesEvent event) { - - long actionStart = System.currentTimeMillis(); + protected List<Action> doSchedule(SsmPackageEvent event, + User user, + List<Long> sids, + Date earliest) {
- Date earliest = event.getEarliest(); - Map<Long, List<Map<String, Long>>> packageListItems = event.getSysPackageSet(); + SsmUpgradePackagesEvent supe = (SsmUpgradePackagesEvent) event; + Map<Long, List<Map<String, Long>>> packageListItems = supe.getSysPackageSet();
- ActionManager.schedulePackageUpgrades(user, packageListItems, earliest); + return ActionManager.schedulePackageUpgrades(user, packageListItems, earliest);
- if (log.isDebugEnabled()) { - log.debug("Time to schedule all actions: " + - (System.currentTimeMillis() - actionStart)); - } }
} - diff --git a/java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesEvent.java b/java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesEvent.java index 119cad7..c065091 100644 --- a/java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesEvent.java +++ b/java/code/src/com/redhat/rhn/frontend/events/SsmUpgradePackagesEvent.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2010 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -14,23 +14,21 @@ */ package com.redhat.rhn.frontend.events;
-import com.redhat.rhn.common.messaging.EventMessage; - import java.util.Date; import java.util.List; import java.util.Map;
+import com.redhat.rhn.domain.action.script.ScriptActionDetails; + /** * Event fired to carry the information necessary to upgrade packages on servers in the * SSM. * * @see com.redhat.rhn.frontend.events.SsmUpgradePackagesAction */ -public class SsmUpgradePackagesEvent implements EventMessage { +public class SsmUpgradePackagesEvent extends SsmPackageEvent {
- private Long userId; - private Date earliest; - private Map<Long, List<Map<String, Long>>> sysPackageSet; + protected Map<Long, List<Map<String, Long>>> sysPackageSet;
/** * Creates a new SSM upgrade packages event. @@ -43,48 +41,51 @@ public class SsmUpgradePackagesEvent implements EventMessage { * name_id -> long * evr_id -> long * arch_id -> long + * @param detailsIn optional remote-command to execute before or after the install + * @param beforeIn optional boolean - true if details should be executed BEFORE the + * install, false if AFTER */ - public SsmUpgradePackagesEvent(Long userIdIn, Date earliestIn, - Map<Long, List<Map<String, Long>>> sysPackageSetIn) { - userId = userIdIn; - earliest = earliestIn; + public SsmUpgradePackagesEvent(Long userIdIn, + Date earliestIn, + Map<Long, List<Map<String, Long>>> sysPackageSetIn, + ScriptActionDetails detailsIn, + boolean beforeIn) { + super(userIdIn, earliestIn, detailsIn, beforeIn); + if (sysPackageSetIn == null) { + throw new IllegalArgumentException("sysPackageSetIn cannot be null"); + } sysPackageSet = sysPackageSetIn; } - - /** {@inheritDoc} */ - public String toText() { - return toString(); - } - - /** {@inheritDoc} */ - public String toString() { - return "SsmUpgradePackagesEvent[User ID: " + userId + "]"; - } - + /** - * Gets the user for this instance. + * Creates a new SSM upgrade packages event. * - * @return The user. + * @param userIdIn ID of user scheduling this action. + * @param earliestIn Earliest data action can be picked up. + * @param sysPackageSetIn Complex map of: + * system id-> List + * Map + * name_id -> long + * evr_id -> long + * arch_id -> long */ - public Long getUserId() { - return this.userId; + public SsmUpgradePackagesEvent(Long userIdIn, + Date earliestIn, + Map<Long, List<Map<String, Long>>> sysPackageSetIn) { + this(userIdIn, earliestIn, sysPackageSetIn, null, false); }
- /** - * Gets the earliest for this instance. - * - * @return The earliest. - */ - public Date getEarliest() { - return this.earliest; + /** {@inheritDoc} */ + public String toString() { + return "SsmUpgradePackagesEvent[" + super.toString() + "]"; }
- /** * @return Returns the sysPackageSet. */ public Map<Long, List<Map<String, Long>>> getSysPackageSet() { return sysPackageSet; } + }
diff --git a/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml b/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml index 24d879a..201f985 100644 --- a/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml +++ b/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml @@ -5698,6 +5698,12 @@ value for this entitlement, excluding the default organization's consumption.</s <context context-type="sourcefile">/rhn/systems/ssm/audit/ScheduleXccdf.do</context> </context-group> </trans-unit> + <trans-unit id="message.capability.missing"> + <source>One or more of the selected systems lack the {0} client-capability.</source> + <context-group name="ctx"> + <context context-type="sourcefile">/rhn/systems/ssm/audit/ScheduleXccdf.do</context> + </context-group> + </trans-unit> <trans-unit id="removeconfirm.jsp.runremotecommand"> <source>Add Remote Command To Package Removal</source> <context-group name="ctx"> @@ -5880,6 +5886,12 @@ value for this entitlement, excluding the default organization's consumption.</s <context context-type="sourcefile">/rhn/systems/details/packages/ScheduleRemoteCommand.do</context> </context-group> </trans-unit> + <trans-unit id="scheduleremote.jsp.ssm.summary"> + <source>You can schedule a remote script to execute on the selected systems below. The script will run as the user you specify.</p> <p>You must enable Remote Command execution on the target system, by adding a file to the local rhn configuration directory: <code>allowed-actions/script/run/</code>.</source> + <context-group name="ctx"> + <context context-type="sourcefile">/rhn/systems/details/packages/ScheduleRemoteCommand.do</context> + </context-group> + </trans-unit> <trans-unit id="scheduleremote.jsp.run"> <source>Run</source> <context-group name="ctx"> diff --git a/java/code/src/com/redhat/rhn/frontend/struts/RequestContext.java b/java/code/src/com/redhat/rhn/frontend/struts/RequestContext.java index 2df7075..0679b53 100644 --- a/java/code/src/com/redhat/rhn/frontend/struts/RequestContext.java +++ b/java/code/src/com/redhat/rhn/frontend/struts/RequestContext.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2010 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -113,6 +113,7 @@ public class RequestContext { public static final String CONFIRM = "confirm"; public static final String FILTER_KEY = "Go"; public static final String NO_SCRIPT = "noscript"; + public static final String MODE = "mode"; /** the name of the Red Hat session cookie */ public static final String WEB_SESSION_COOKIE_NAME = "pxt-session-cookie"; public static final String POST = "POST"; diff --git a/java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java b/java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java index 240ba17..c21af31 100644 --- a/java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java +++ b/java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java @@ -3434,7 +3434,7 @@ public class SystemHandler extends BaseHandler { new Long(timeout.longValue()), script); ScriptAction action = null;
- List<Server> servers = new ArrayList<Server>(); + List<Long> servers = new ArrayList<Long>();
for (Iterator<Integer> sysIter = systemIds.iterator(); sysIter.hasNext();) { Integer sidAsInt = sysIter.next(); @@ -3444,7 +3444,7 @@ public class SystemHandler extends BaseHandler { try { server = SystemManager.lookupByIdAndUser(new Long(sid.longValue()), loggedInUser); - servers.add(server); + servers.add(sid); } catch (LookupException e) { throw new NoSuchSystemException(); diff --git a/java/code/src/com/redhat/rhn/manager/MissingCapabilityException.java b/java/code/src/com/redhat/rhn/manager/MissingCapabilityException.java index 48d585d..2a12b78 100644 --- a/java/code/src/com/redhat/rhn/manager/MissingCapabilityException.java +++ b/java/code/src/com/redhat/rhn/manager/MissingCapabilityException.java @@ -16,6 +16,7 @@ package com.redhat.rhn.manager;
import com.redhat.rhn.common.RhnRuntimeException; import com.redhat.rhn.domain.server.Server; +import com.redhat.rhn.domain.server.ServerFactory;
/** * MissingCapabilityException @@ -33,16 +34,23 @@ public class MissingCapabilityException extends RhnRuntimeException { /** * Constructor for exception on missing capability on a bunch of servers. * @param missingCapability the missing capability. - * @param incapableServer the server missing the capaibility + * @param incapableServer the server missing the capability */ public MissingCapabilityException(String missingCapability, Server incapableServer) { - - server = incapableServer; capability = missingCapability; }
+ /** + * Constructor for exception on missing capability on a bunch of servers. + * + * @param missingCapability the missing capability. + * @param sid the ID of the server missing the capability + */ + public MissingCapabilityException(String missingCapability, Long sid) { + this(missingCapability, ServerFactory.lookupById(sid)); + }
/** * @return the servers missing the given capability diff --git a/java/code/src/com/redhat/rhn/manager/action/ActionManager.java b/java/code/src/com/redhat/rhn/manager/action/ActionManager.java index 4697c16..1e25e20 100644 --- a/java/code/src/com/redhat/rhn/manager/action/ActionManager.java +++ b/java/code/src/com/redhat/rhn/manager/action/ActionManager.java @@ -1226,21 +1226,27 @@ public class ActionManager extends BaseManager { return (PackageAction) schedulePackageAction(scheduler, pkgs, ActionFactory.TYPE_PACKAGES_REMOVE, earliestAction, srvr); } - return (PackageAction) schedulePackageAction(scheduler, pkgs, - ActionFactory.TYPE_SOLARISPKGS_REMOVE, earliestAction, srvr); + else { + return (PackageAction) schedulePackageAction(scheduler, pkgs, + ActionFactory.TYPE_SOLARISPKGS_REMOVE, earliestAction, srvr); + } }
/** * Schedules one or more package removal actions on one or more servers. * * @param scheduler user scheduling the action. - * @param serverIds servers from which to remove the packages + * @param serverIds servers from which to remove the packages * @param pkgs list of packages to be removed. * @param earliestAction date of earliest action to be executed + * @return List of actions (can be more than one, if mix of Solaris/Rhel servers) */ - public static void schedulePackageRemoval(User scheduler, + public static List<Action> schedulePackageRemoval(User scheduler, Collection<Long> serverIds, List<Map<String, Long>> pkgs, Date earliestAction) {
+ List<Action> actions = new ArrayList<Action>(); + Action anAction; + // Different handling for package removal on solaris v. rhel, so split out // the servers first in case the list is mixed. Set<Long> rhelServers = new HashSet<Long>(); @@ -1251,33 +1257,38 @@ public class ActionManager extends BaseManager { // Since the solaris v. rhel distinction results in a different action type, // we'll end up with 2 actions created if the server list is mixed if (!rhelServers.isEmpty()) { - schedulePackageAction(scheduler, pkgs, ActionFactory.TYPE_PACKAGES_REMOVE, - earliestAction, rhelServers); + anAction = schedulePackageAction(scheduler, pkgs, + ActionFactory.TYPE_PACKAGES_REMOVE, earliestAction, rhelServers); + actions.add(anAction); }
if (!solarisServers.isEmpty()) { - schedulePackageAction(scheduler, pkgs, ActionFactory.TYPE_SOLARISPKGS_REMOVE, - earliestAction, solarisServers); + anAction = schedulePackageAction(scheduler, pkgs, + ActionFactory.TYPE_SOLARISPKGS_REMOVE, earliestAction, solarisServers); + actions.add(anAction); } + return actions; }
/** * Schedules one or more package upgrade actions for the given servers. * Note: package upgrade = package install * @param scheduler User scheduling the action. - * @param sysPkgMapping The set of packages to be removed. + * @param sysPkgMapping The set of packages to be upgraded. * @param earliestAction Date of earliest action to be executed + * @return actions list of all scheduled upgrades */ - public static void schedulePackageUpgrades(User scheduler, + public static List<Action> schedulePackageUpgrades(User scheduler, Map<Long, List<Map<String, Long>>> sysPkgMapping, Date earliestAction) { + List<Action> actions = new ArrayList<Action>();
for (Long sid : sysPkgMapping.keySet()) { List<Long> ids = new ArrayList<Long>(); ids.add(sid); - schedulePackageInstall(scheduler, ids, sysPkgMapping.get(sid), earliestAction); + actions.addAll(schedulePackageInstall(scheduler, ids, sysPkgMapping.get(sid), + earliestAction)); } - - + return actions; }
/** @@ -1318,10 +1329,14 @@ public class ActionManager extends BaseManager { * @param serverIds server ids for which the packages should be installed * @param pkgs set of packages to be removed. * @param earliestAction date of earliest action to be executed + * @return TODO */ - public static void schedulePackageInstall(User scheduler, + public static List<Action> schedulePackageInstall(User scheduler, Collection<Long> serverIds, List pkgs, Date earliestAction) {
+ List<Action> actions = new ArrayList<Action>(); + Action anAction; + // Different handling for package installs on solaris v. rhel, so split out // the servers first in case the list is mixed. Set<Long> rhelServers = new HashSet<Long>(); @@ -1332,15 +1347,17 @@ public class ActionManager extends BaseManager { // Since the solaris v. rhel distinction results in a different action type, // we'll end up with 2 actions created if the server list is mixed if (!rhelServers.isEmpty()) { - schedulePackageAction(scheduler, pkgs, ActionFactory.TYPE_PACKAGES_UPDATE, - earliestAction, rhelServers); + anAction = schedulePackageAction(scheduler, pkgs, + ActionFactory.TYPE_PACKAGES_UPDATE, earliestAction, rhelServers); + actions.add(anAction); }
if (!solarisServers.isEmpty()) { - schedulePackageAction(scheduler, pkgs, ActionFactory.TYPE_SOLARISPKGS_INSTALL, - earliestAction, solarisServers); + anAction = schedulePackageAction(scheduler, pkgs, + ActionFactory.TYPE_SOLARISPKGS_INSTALL, earliestAction, solarisServers); + actions.add(anAction); } - + return actions; }
/** @@ -1370,39 +1387,41 @@ public class ActionManager extends BaseManager { return (PackageAction) schedulePackageAction(scheduler, pkgs, ActionFactory.TYPE_PACKAGES_VERIFY, earliest, srvr); } + /** * Schedules a script action for the given servers + * * @param scheduler User scheduling the action. - * @param servers Servers for which the action affects. + * @param sids Servers for which the action affects. * @param script The set of packages to be removed. * @param name Name of Script action. * @param earliest Earliest occurrence of the script. * @return Currently scheduled ScriptRunAction + * @throws MissingCapabilityException if any server in the list is missing script.run; + * schedule fails + * @throws MissingEntitlementException if any server in the list is missing + * Provisioning; schedule fails */ - public static ScriptRunAction scheduleScriptRun(User scheduler, - List servers, String name, ScriptActionDetails script, Date earliest) { + public static ScriptRunAction scheduleScriptRun(User scheduler, List<Long> sids, + String name, ScriptActionDetails script, Date earliest) {
- // server IDs to schedule - Set serverIds = new HashSet(); - - for (Iterator sysIter = servers.iterator(); sysIter.hasNext();) { - Server srvr = (Server) sysIter.next(); - - if (!SystemManager.clientCapable(srvr.getId(), "script.run")) { - throw new MissingCapabilityException("script.run", srvr); + for (Long sid : sids) { + if (!SystemManager.clientCapable(sid, "script.run")) { + throw new MissingCapabilityException("script.run", sid); }
- if (!SystemManager.hasEntitlement(srvr.getId(), - EntitlementManager.PROVISIONING)) { + if (!SystemManager.hasEntitlement(sid, EntitlementManager.PROVISIONING)) { throw new MissingEntitlementException( EntitlementManager.PROVISIONING.getHumanReadableLabel()); } - - serverIds.add(srvr.getId()); }
+ Set<Long> sidSet = new HashSet<Long>(); + sidSet.addAll(sids); + + // Only execute if all servers have capability script.run and Provisioning ScriptRunAction sra = (ScriptRunAction) scheduleAction(scheduler, - ActionFactory.TYPE_SCRIPT_RUN, name, earliest, serverIds); + ActionFactory.TYPE_SCRIPT_RUN, name, earliest, sidSet); sra.setScriptActionDetails(script); ActionFactory.save(sra); return sra; diff --git a/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java b/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java index ea0de7b..5cbb66f 100644 --- a/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java +++ b/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2009--2012 Red Hat, Inc. + * Copyright (c) 2009--2013 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 @@ -235,4 +235,23 @@ public class SsmManager { set.clear(); RhnSetManager.store(set); } + + /** + * Returns a list of server-ids of the servers in the SSM selection, for the specified + * user + * + * @param user user whose system-set we care about + * @return list of server-ids + */ + public static List<Long> listServerIds(User user) { + RhnSet ssm = RhnSetDecl.SYSTEMS.lookup(user); + List<Long> sids = new ArrayList<Long>(); + if (ssm != null) { + for (RhnSetElement rse : ssm.getElements()) { + sids.add(rse.getElement()); + } + } + return sids; + } + } diff --git a/java/code/webapp/WEB-INF/pages/ssm/packageinstallschedule.jsp b/java/code/webapp/WEB-INF/pages/ssm/packageinstallschedule.jsp index 782917b..92622fc 100644 --- a/java/code/webapp/WEB-INF/pages/ssm/packageinstallschedule.jsp +++ b/java/code/webapp/WEB-INF/pages/ssm/packageinstallschedule.jsp @@ -71,12 +71,15 @@ <hr/> <input type="submit" name="dispatch" + value='<bean:message key="installconfirm.jsp.runremotecommand"/>'/> + <input type="submit" + name="dispatch" value='<bean:message key="installconfirm.jsp.confirm"/>'/> </div>
<input type="hidden" name="packagesDecl" value="${requestScope.packagesDecl}" /> <input type="hidden" name="cid" value="${param.cid}" /> - + <input type="hidden" name="mode" value="${param.mode}" /> </rl:listset>
</body> diff --git a/java/code/webapp/WEB-INF/pages/ssm/packagelist.jsp b/java/code/webapp/WEB-INF/pages/ssm/packagelist.jsp index bb47a6a..8fca3e7 100644 --- a/java/code/webapp/WEB-INF/pages/ssm/packagelist.jsp +++ b/java/code/webapp/WEB-INF/pages/ssm/packagelist.jsp @@ -54,6 +54,8 @@ </div>
</rl:listset> +<html:hidden property="cid" value="${param.cid}" /> +<html:hidden property="mode" value="${param.mode}" />
</body> </html> diff --git a/java/code/webapp/WEB-INF/pages/ssm/packageremoveschedule.jsp b/java/code/webapp/WEB-INF/pages/ssm/packageremoveschedule.jsp index 647a042..d3776f9 100644 --- a/java/code/webapp/WEB-INF/pages/ssm/packageremoveschedule.jsp +++ b/java/code/webapp/WEB-INF/pages/ssm/packageremoveschedule.jsp @@ -80,11 +80,14 @@ <hr/> <input type="submit" name="dispatch" + value='<bean:message key="removeconfirm.jsp.runremotecommand"/>'/> + <input type="submit" + name="dispatch" value='<bean:message key="installconfirm.jsp.confirm"/>'/> </div>
<input type="hidden" name="packagesDecl" value="${requestScope.packagesDecl}" /> - <input type="hidden" name="cid" value="${param.cid}" /> + <input type="hidden" name="mode" value="${param.mode}" />
</rl:listset>
diff --git a/java/code/webapp/WEB-INF/pages/ssm/packagescheduleremote.jsp b/java/code/webapp/WEB-INF/pages/ssm/packagescheduleremote.jsp new file mode 100644 index 0000000..e6f1fc6 --- /dev/null +++ b/java/code/webapp/WEB-INF/pages/ssm/packagescheduleremote.jsp @@ -0,0 +1,80 @@ +<%@ taglib uri="http://rhn.redhat.com/rhn" prefix="rhn" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> +<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> + +html:xhtml/ +<html> + +<body> +<%@ include file="/WEB-INF/pages/common/fragments/ssm/header.jspf" %> + +<h2><bean:message key="scheduleremote.jsp.scheduleremotecommand"/></h2> + +<div class="page-summary"> + <p><bean:message key="scheduleremote.jsp.ssm.summary"/></p> +</div> + +<html:form action="/ssm/PackageScheduleRemoteCommand"> + <rhn:csrf /> + <table class="details" align="center"> + <tr> + <th><bean:message key="scheduleremote.jsp.run"/></th> + <td> + <html:radio property="run_script" value="before" /><bean:message key="scheduleremote.jsp.beforepackageaction"/> + <br/> + <html:radio property="run_script" value="after" /><bean:message key="scheduleremote.jsp.afterpackageaction"/> + </td> + </tr> + <tr> + <th><bean:message key="scheduleremote.jsp.runasuser"/>:</th> + <td><html:text property="username" maxlength="32" /></td> + </tr> + <tr> + <th><bean:message key="scheduleremote.jsp.runasgroup" />:</th> + <td><html:text property="group" maxlength="32" /></td> + </tr> + <tr> + <th><bean:message key="scheduleremote.jsp.timeout" />:</th> + <td><html:text property="timeout" maxlength="" size="6" /></td> + </tr> + <tr> + <th><bean:message key="scheduleremote.jsp.script" />:</th> + <td><html:textarea property="script" cols="80" rows="8" /></td> + </tr> + <tr> + <th><bean:message key="scheduleremote.jsp.nosoonerthan" />:</th> + <td> + ${requestScope.scheduledDate} + </td> + </tr> + </table> + +<html:hidden property="session_set_label" value="${param.packagesDecl}" /> +<html:hidden property="cid" value="${param.cid}" /> +<html:hidden property="mode" value="${param.mode}" /> +<html:hidden property="submitted" value="true" /> +<html:hidden property="use_date" value="true"/> +<%@ include file="/WEB-INF/pages/common/fragments/date-picker-hidden.jspf" %> + + <div align="right"> + <hr /> + <c:if test="${param.mode == 'remove'}"> + html:submit + <bean:message key="scheduleremote.jsp.schedulepackageremoval"/> + </html:submit> + </c:if> + <c:if test="${param.mode == 'upgrade'}"> + html:submit + <bean:message key="scheduleremote.jsp.schedulepackageupgrade"/> + </html:submit> + </c:if> + <c:if test="${param.mode == 'install'}"> + html:submit + <bean:message key="scheduleremote.jsp.schedulepackageinstall"/> + </html:submit> + </c:if> + </div> +</html:form> +</body> +</html> diff --git a/java/code/webapp/WEB-INF/pages/ssm/packageupgradeschedule.jsp b/java/code/webapp/WEB-INF/pages/ssm/packageupgradeschedule.jsp index ac9dbd1..4911626 100644 --- a/java/code/webapp/WEB-INF/pages/ssm/packageupgradeschedule.jsp +++ b/java/code/webapp/WEB-INF/pages/ssm/packageupgradeschedule.jsp @@ -85,11 +85,14 @@ <hr/> <input type="submit" name="dispatch" + value='<bean:message key="upgradeconfirm.jsp.runremotecommand"/>'/> + <input type="submit" + name="dispatch" value='<bean:message key="installconfirm.jsp.confirm"/>'/> </div>
<input type="hidden" name="packagesDecl" value="${requestScope.packagesDecl}" /> - <input type="hidden" name="cid" value="${param.cid}" /> + <input type="hidden" name="mode" value="${param.mode}" />
</rl:listset>
diff --git a/java/code/webapp/WEB-INF/struts-config.xml b/java/code/webapp/WEB-INF/struts-config.xml index a224ad5..04a9e16 100644 --- a/java/code/webapp/WEB-INF/struts-config.xml +++ b/java/code/webapp/WEB-INF/struts-config.xml @@ -7857,6 +7857,21 @@ <set-property property="postRequiredIfSubmitted" value="true" /> <forward name="default" path="/WEB-INF/pages/ssm/packageinstallschedule.jsp" /> + <forward name="remote" + path="/ssm/PackageScheduleRemoteCommand.do" redirect="true"/> + <forward name="confirm" + path="/ssm/ViewLog.do" redirect="true"/> + </action> + + <action path="/ssm/PackageScheduleRemoteCommand" + scope="request" + name="scheduleRemoteCmdForm" + input="/WEB-INF/pages/ssm/packagescheduleremote.jsp" + type="com.redhat.rhn.frontend.action.rhnpackage.ssm.ScheduleRemoteCommand" + className="com.redhat.rhn.frontend.struts.RhnActionMapping"> + <set-property property="postRequiredIfSubmitted" value="true" /> + <forward name="default" + path="/WEB-INF/pages/ssm/packagescheduleremote.jsp" /> <forward name="confirm" path="/ssm/ViewLog.do" redirect="true"/> </action> @@ -7883,6 +7898,8 @@ <set-property property="postRequiredIfSubmitted" value="true" /> <forward name="default" path="/WEB-INF/pages/ssm/packageremoveschedule.jsp" /> + <forward name="remote" + path="/ssm/PackageScheduleRemoteCommand.do" redirect="true"/> <forward name="confirm" path="/ssm/ViewLog.do" redirect="true"/> </action> @@ -7909,6 +7926,8 @@ <set-property property="postRequiredIfSubmitted" value="true" /> <forward name="default" path="/WEB-INF/pages/ssm/packageupgradeschedule.jsp" /> + <forward name="remote" + path="/ssm/PackageScheduleRemoteCommand.do" redirect="true"/> <forward name="confirm" path="/ssm/ViewLog.do" redirect="true"/> </action>
spacewalk-commits@lists.fedorahosted.org