/**
* Copyright (c) 2009--2015 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.frontend.action.kickstart;
import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.common.security.PermissionException;
import com.redhat.rhn.common.validator.ValidatorException;
import com.redhat.rhn.domain.channel.Channel;
import com.redhat.rhn.domain.kickstart.KickstartData;
import com.redhat.rhn.domain.kickstart.KickstartFactory;
import com.redhat.rhn.domain.kickstart.KickstartVirtualizationType;
import com.redhat.rhn.domain.kickstart.KickstartableTree;
import com.redhat.rhn.domain.kickstart.builder.KickstartBuilder;
import com.redhat.rhn.frontend.struts.RequestContext;
import com.redhat.rhn.frontend.struts.RhnValidationHelper;
import com.redhat.rhn.frontend.struts.wizard.RhnWizardAction;
import com.redhat.rhn.frontend.struts.wizard.WizardStep;
import com.redhat.rhn.manager.acl.AclManager;
import com.redhat.rhn.manager.kickstart.KickstartWizardHelper;
import org.apache.log4j.Logger;
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 java.lang.reflect.Method;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Manages the workflow for the Create New Kickstart Profile wizard
*
* @version $Rev $
*/
public class CreateProfileWizardAction extends RhnWizardAction {
private static final String PREV_CHAN_ID = "previousChannelId";
private static final String CURR_CHAN_ID = "currentChannelId";
private static final String PREV_STEP_PARAM = "prevStep";
private static final String NEXT_STEP_PARAM = "nextStep";
private static final String KICKSTART_LABEL_PARAM = "kickstartLabel";
private static final String KSTREE_ID_PARAM = "kstreeId";
private static final String USE_NEWEST_KSTREE_PARAM = "useNewestTree";
private static final String USE_NEWEST_RH_KSTREE_PARAM = "useNewestRHTree";
private static final String CURRENT_CHANNEL_ID_PARAM = "currentChannelId";
private static final String RED_HAT_TREES_AVAILABLE = "redHatTreesAvailable";
private static final String KSTREE_UPDATE_TYPE = "kstreeUpdateType";
private static final String DEFAULT_DOWNLOAD_PARAM = "defaultDownload";
private static final String USER_DOWNLOAD_PARAM = "userDefinedDownload";
private static final String ROOT_PASSWORD_PARAM = "rootPassword";
private static final String ROOT_PASSWORD_CONFIRM_PARAM = "rootPasswordConfirm";
private static final String DEFAULT_DOWNLOAD_LOCN = "defaultDownloadLocation";
public static final String CHANNELS = "channels";
public static final String KSTREES_PARAM = "kstrees";
public static final String NOTREES_PARAM = "notrees";
public static final String NOCHANNELS_PARAM = "nochannels";
public static final String VIRTUALIZATION_TYPES_PARAM = "virtualizationTypes";
public static final String VIRTUALIZATION_TYPE_LABEL_PARAM = "virtualizationTypeLabel";
private static Logger log = Logger.getLogger(CreateProfileWizardAction.class);
/**
*
* {@inheritDoc}
*/
@Override
public ActionForward execute(ActionMapping mapping,
ActionForm formIn,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (!AclManager.hasAcl("user_role(org_admin) or user_role(config_admin)",
request, null)) {
//Throw an exception with a nice error message so the user
//knows what went wrong.
LocalizationService ls = LocalizationService.getInstance();
PermissionException pex = new PermissionException("Only Org Admins or " +
"Configuration Admins can modify kickstarts");
pex.setLocalizedTitle(ls.getMessage("permission.jsp.summary.acl.header"));
pex.setLocalizedSummary(ls.getMessage("permission.jsp.summary.acl.reason5"));
throw pex;
}
return super.execute(mapping, formIn, request, response);
}
@Override
protected void generateWizardSteps(Map steps) {
List methods = findMethods("run");
for (Iterator iter = methods.iterator(); iter.hasNext();) {
Method m = (Method) iter.next();
if (m.getName().startsWith("run")) {
String stepName = m.getName().substring(3).toLowerCase();
WizardStep wizStep = new WizardStep();
wizStep.setWizardMethod(m);
if (stepName.equals("first")) {
wizStep.setNext("second");
steps.put(RhnWizardAction.STEP_START, wizStep);
}
else if (stepName.equals("second")) {
wizStep.setPrevious("first");
wizStep.setNext("third");
}
else if (stepName.equals("third")) {
wizStep.setPrevious("second");
wizStep.setNext("complete");
}
else if (stepName.equals("complete")) {
wizStep.setPrevious("third");
}
steps.put(stepName, wizStep);
}
else {
continue;
}
}
}
private ActionForward runFirst(ActionMapping mapping, DynaActionForm form,
RequestContext ctx, HttpServletResponse response,
WizardStep step) throws Exception {
KickstartWizardHelper cmd = new KickstartWizardHelper(ctx.getCurrentUser());
List channels = cmd.getAvailableChannels();
if (channels == null || channels.size() == 0) {
ctx.getRequest().setAttribute(NOCHANNELS_PARAM, "true");
}
form.set(CHANNELS, channels);
setCurrentChannel(form);
loadTrees(cmd, form, ctx.getRequest());
loadVirtualizationTypes(cmd, form, ctx.getRequest());
form.set(PREV_STEP_PARAM, "");
form.set(NEXT_STEP_PARAM, "second");
ActionForward retval = null;
retval = mapping.findForward("first");
return retval;
}
private ActionForward runSecond(ActionMapping mapping, DynaActionForm form,
RequestContext ctx, HttpServletResponse response,
WizardStep step) throws Exception {
List<String> fields = new LinkedList<String>();
KickstartTreeUpdateType updateType = null;
fields.add(KICKSTART_LABEL_PARAM);
if (form.get(USE_NEWEST_KSTREE_PARAM) != null) {
updateType = KickstartTreeUpdateType.ALL;
}
else if (form.get(USE_NEWEST_RH_KSTREE_PARAM) != null) {
updateType = KickstartTreeUpdateType.RED_HAT;
}
else {
updateType = KickstartTreeUpdateType.NONE;
fields.add(KSTREE_ID_PARAM);
}
if (!validateInput(form, fields, ctx)) {
return this.dispatch(step.getPrevious(), mapping, form, ctx, response);
}
try {
String kickstartLabel = form.getString(KICKSTART_LABEL_PARAM);
KickstartBuilder builder = new KickstartBuilder(ctx.getCurrentUser());
try {
builder.validateNewLabel(kickstartLabel);
}
catch (ValidatorException ve) {
getStrutsDelegate().saveMessages(ctx.getRequest(), ve.getResult());
return this.dispatch(step.getPrevious(), mapping, form, ctx, response);
}
Long channelId = (Long) form.get(CURRENT_CHANNEL_ID_PARAM);
KickstartWizardHelper cmd = new KickstartWizardHelper(ctx.getCurrentUser());
ActionForward retval = null;
KickstartableTree tree = null;
if (updateType == KickstartTreeUpdateType.NONE) {
tree = cmd.getKickstartableTree((Long) form
.get(KSTREE_ID_PARAM));
}
else {
tree = KickstartFactory.getNewestTree(updateType, channelId,
ctx.getCurrentUser().getOrg());
form.set(KSTREE_ID_PARAM, tree.getId());
}
form.set(KSTREE_UPDATE_TYPE, updateType.getType());
form.set(PREV_STEP_PARAM, "first");
form.set(NEXT_STEP_PARAM, "third");
form.set(
DEFAULT_DOWNLOAD_LOCN,
getDefaultDisplayDownloadLocation(tree));
ctx.getRequest().setAttribute("selectedTree", tree);
builder.validateTreeVirt(
tree, form.getString(VIRTUALIZATION_TYPE_LABEL_PARAM));
if (form.get(DEFAULT_DOWNLOAD_PARAM) == null) {
form.set(DEFAULT_DOWNLOAD_PARAM, Boolean.TRUE);
}
retval = mapping.findForward("second");
return retval;
}
catch (ValidatorException ve) {
getStrutsDelegate().saveMessages(ctx.getRequest(), ve.getResult());
return this.dispatch(step.getPrevious(), mapping, form, ctx, response);
}
}
private ActionForward runThird(ActionMapping mapping, DynaActionForm form,
RequestContext ctx, HttpServletResponse response,
WizardStep step) throws Exception {
List<String> fields = new LinkedList<String>();
fields.add(DEFAULT_DOWNLOAD_PARAM);
if (!validateInput(form, fields, ctx)) {
return this.dispatch(step.getPrevious(), mapping, form, ctx, response);
}
Boolean usingDefaultLocation =
(Boolean) form.get(DEFAULT_DOWNLOAD_PARAM);
if (usingDefaultLocation != null && usingDefaultLocation.equals(Boolean.FALSE)) {
fields.clear();
fields = new LinkedList();
fields.add(USER_DOWNLOAD_PARAM);
if (!validateInput(form, fields, ctx)) {
form.set(DEFAULT_DOWNLOAD_PARAM, Boolean.FALSE);
return this.dispatch(step.getPrevious(), mapping, form, ctx, response);
}
String userDownload = form.getString(USER_DOWNLOAD_PARAM);
userDownload = userDownload.toLowerCase();
if (!userDownload.startsWith("http://") &&
!userDownload.startsWith("ftp://")) {
ActionErrors errs = new ActionErrors();
errs.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("invalidUserDefinedDownload"));
saveMessages(ctx.getRequest(), errs);
return this.dispatch(step.getPrevious(), mapping, form, ctx, response);
}
}
form.set(PREV_STEP_PARAM, "second");
form.set(NEXT_STEP_PARAM, "complete");
return mapping.findForward("third");
}
private ActionForward runComplete(ActionMapping mapping, DynaActionForm form,
RequestContext ctx, HttpServletResponse response,
WizardStep step) throws Exception {
log.debug("CreateProfileWizard.runComplete()");
KickstartWizardHelper cmd = new KickstartWizardHelper(ctx.getCurrentUser());
List<String> fields = new LinkedList<String>();
fields.add(ROOT_PASSWORD_PARAM);
fields.add(ROOT_PASSWORD_CONFIRM_PARAM);
if (!validateInput(form, fields, ctx) ||
!passwdsEqual(form.getString(ROOT_PASSWORD_PARAM),
form.getString(ROOT_PASSWORD_CONFIRM_PARAM), ctx)) {
return this.dispatch(step.getPrevious(), mapping, form, ctx, response);
}
KickstartableTree tree = cmd.getKickstartableTree((Long) form
.get(KSTREE_ID_PARAM));
KickstartTreeUpdateType updateType = KickstartTreeUpdateType
.find((String) form.get(KSTREE_UPDATE_TYPE));
Boolean useDefault = (Boolean) form.get(DEFAULT_DOWNLOAD_PARAM);
String downloadUrl = null;
if (useDefault != null && Boolean.TRUE.equals(useDefault)) {
downloadUrl = tree.getDefaultDownloadLocation();
}
else {
downloadUrl = form.getString(USER_DOWNLOAD_PARAM);
}
log.debug("Using download location: " + downloadUrl);
String ksLabel = form.getString(KICKSTART_LABEL_PARAM);
String rootPass = form.getString(ROOT_PASSWORD_PARAM);
String virtType = form.getString(VIRTUALIZATION_TYPE_LABEL_PARAM);
KickstartBuilder builder = new KickstartBuilder(ctx.getCurrentUser());
KickstartData ksdata = builder.create(ksLabel, tree, virtType,
downloadUrl, rootPass, updateType);
String url = ctx.getRequest().getContextPath() + "/kickstart/" +
"KickstartDetailsEdit.do?ksid=" + ksdata.getId();
response.sendRedirect(url);
return null;
}
private void loadTrees(KickstartWizardHelper cmd, DynaActionForm form,
HttpServletRequest request) {
Long currentChanId = (Long) form.get(CURR_CHAN_ID);
Long prevChanId = (Long) form.get(PREV_CHAN_ID);
if (currentChanId != null && prevChanId != null) {
List<KickstartableTree> trees = cmd.getTrees(currentChanId);
for (KickstartableTree tree : trees) {
if (tree.getOrg() == null) {
request.setAttribute(RED_HAT_TREES_AVAILABLE, "true");
break;
}
}
if (trees == null || trees.size() == 0) {
request.setAttribute(NOTREES_PARAM, "true");
}
else {
form.set(KSTREES_PARAM, trees);
if (!currentChanId.equals(prevChanId)) {
form.set(PREV_CHAN_ID, currentChanId);
KickstartableTree tree = trees.get(trees.size() - 1);
form.set(KSTREE_ID_PARAM, tree.getId());
}
}
}
else {
request.setAttribute(NOTREES_PARAM, "true");
}
}
private void loadVirtualizationTypes(KickstartWizardHelper cmd, DynaActionForm form,
HttpServletRequest request) {
List types = cmd.getVirtualizationTypes();
form.set(VIRTUALIZATION_TYPES_PARAM, types);
form.set(VIRTUALIZATION_TYPE_LABEL_PARAM,
KickstartVirtualizationType.NONE);
}
private void setCurrentChannel(DynaActionForm form) {
Long currentChanId = (Long) form.get(CURR_CHAN_ID);
Long prevChanId = (Long) form.get(PREV_CHAN_ID);
if (currentChanId == null && prevChanId != null) {
form.set(CURR_CHAN_ID, prevChanId);
}
else if (currentChanId == null || prevChanId == null) {
List channels = (List) form.get(CHANNELS);
if (channels != null && channels.size() > 0) {
Channel channel = (Channel) channels.get(0);
form.set(CURR_CHAN_ID, channel.getId());
form.set(PREV_CHAN_ID, channel.getId());
}
}
}
private boolean validateInput(DynaActionForm form, List fieldNames,
RequestContext ctx) {
ActionErrors errs =
RhnValidationHelper.validateDynaActionForm(this, form, fieldNames);
boolean retval = errs.size() == 0;
if (!retval) {
saveMessages(ctx.getRequest(), errs);
}
return retval;
}
private boolean passwdsEqual(String root, String confirm, RequestContext rctx) {
if (!root.equals(confirm)) {
ActionMessages msg = new ActionMessages();
msg.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("root_confirm_passwds.mismatch"));
getStrutsDelegate().saveMessages(rctx.getRequest(), msg);
return false;
}
return true;
}
/**
* Display the default download location including a hostname. This hostname will be
* either the hostname of the proxy the user is
* hitting, or the hostname of the satellite. (depending on availablity, in that
* order)
*/
private String getDefaultDisplayDownloadLocation(KickstartableTree tree) {
if (tree != null) {
return tree.getDefaultDownloadLocation();
}
return "";
}
}