/**
* Copyright (c) 2009--2014 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.conf.Config;
import com.redhat.rhn.common.conf.ConfigDefaults;
import com.redhat.rhn.common.db.datasource.DataResult;
import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.common.util.DatePicker;
import com.redhat.rhn.common.validator.ValidatorError;
import com.redhat.rhn.domain.action.ActionFactory;
import com.redhat.rhn.domain.channel.Channel;
import com.redhat.rhn.domain.kickstart.KickstartCommand;
import com.redhat.rhn.domain.kickstart.KickstartData;
import com.redhat.rhn.domain.kickstart.KickstartFactory;
import com.redhat.rhn.domain.kickstart.KickstartableTree;
import com.redhat.rhn.domain.rhnpackage.profile.Profile;
import com.redhat.rhn.domain.server.NetworkInterface;
import com.redhat.rhn.domain.server.Server;
import com.redhat.rhn.domain.server.VirtualInstanceFactory;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.frontend.action.systems.sdc.SdcHelper;
import com.redhat.rhn.frontend.dto.OrgProxyServer;
import com.redhat.rhn.frontend.dto.ProfileDto;
import com.redhat.rhn.frontend.dto.kickstart.KickstartDto;
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.frontend.taglibs.list.ListTagHelper;
import com.redhat.rhn.frontend.taglibs.list.helper.ListHelper;
import com.redhat.rhn.frontend.taglibs.list.helper.Listable;
import com.redhat.rhn.manager.kickstart.KickstartScheduleCommand;
import com.redhat.rhn.manager.kickstart.cobbler.CobblerSystemCreateCommand;
import com.redhat.rhn.manager.kickstart.cobbler.CobblerXMLRPCHelper;
import com.redhat.rhn.manager.system.SystemManager;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.struts.action.ActionErrors;
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 org.apache.struts.util.LabelValueBean;
import org.cobbler.CobblerConnection;
import org.cobbler.CobblerObject;
import org.cobbler.Distro;
import org.cobbler.SystemRecord;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* blah blah
*
* @version $Rev $
*/
public class ScheduleKickstartWizardAction extends RhnWizardAction {
/**
* Logger for this class
*/
private static Logger log = Logger
.getLogger(ScheduleKickstartWizardAction.class);
public static final String SYNCH_PACKAGES = "syncPackages";
public static final String SYNCH_SYSTEMS = "syncSystems";
public static final String HAS_PROFILES = "hasProfiles";
public static final String HAS_PROXIES = "hasProxies";
public static final String SYNC_PACKAGE_DISABED = "syncPackageDisabled";
public static final String SYNC_SYSTEM_DISABLED = "syncSystemDisabled";
public static final String PROXIES = "proxies";
public static final String CNAMES = "cnames";
public static final String VALID_CNAMES = "valid_cnames_";
public static final String KERNEL_PARAMS = "kernelParams";
public static final String KERNEL_PARAMS_TYPE = "kernelParamsType";
public static final String KERNEL_PARAMS_DISTRO = "distro";
public static final String KERNEL_PARAMS_PROFILE = "profile";
public static final String KERNEL_PARAMS_CUSTOM = "custom";
private static final String COBBLER_ONLY_PROFILE = "cobblerOnlyProfile";
public static final String POST_KERNEL_PARAMS = "postKernelParams";
public static final String POST_KERNEL_PARAMS_TYPE = "postKernelParamsType";
public static final String PROXY_HOST = "proxyHost";
public static final String PROXY_HOST_CNAME = "proxyHostCname";
public static final String IS_VIRTUAL_GUEST = "isVirtualGuest";
public static final String HOST_SID = "hostSid";
public static final String VIRT_HOST_IS_REGISTERED = "virtHostIsRegistered";
public static final String TARGET_PROFILE_TYPE = "targetProfileType";
public static final String NETWORK_TYPE = "networkType";
public static final String NETWORK_INTERFACE = "networkInterface";
public static final String NETWORK_INTERFACES = "networkInterfaces";
public static final String ALL_NETWORK_INTERFACES = "allNetworkInterfaces";
public static final String USE_IPV6_GATEWAY = "useIpv6Gateway";
public static final String BOND_TYPE = "bondType";
public static final String BOND_INTERFACE = "bondInterface";
public static final String BOND_SLAVE_INTERFACES = "bondSlaveInterfaces";
public static final String HIDDEN_BOND_SLAVE_INTERFACES = "hiddenBondSlaveInterfaces";
public static final String BOND_STATIC = "bondStatic";
public static final String BOND_IP_ADDRESS = "bondAddress";
public static final String BOND_NETMASK = "bondNetmask";
public static final String BOND_GATEWAY = "bondGateway";
public static final String BOND_OPTIONS = "bondOptions";
public static final String CREATE_BOND_VALUE = "bonding";
public static final String STATIC_BOND_VALUE = "true";
public static final String DONT_CREATE_BOND_VALUE = "none";
public static final String DESTROY_DISKS = "destroyDisks";
public static final String NEXT_ACTION = "wizardStep";
/**
* {@inheritDoc}
*/
@Override
protected void generateWizardSteps(Map wizardSteps) {
List<Method> methods = findMethods("run");
for (Iterator<Method> iter = methods.iterator(); iter.hasNext();) {
Method m = iter.next();
String stepName = m.getName().substring(3).toLowerCase();
WizardStep wizStep = new WizardStep();
wizStep.setWizardMethod(m);
log.debug("Step name: " + stepName);
if (stepName.equals("first")) {
wizStep.setNext("second");
wizardSteps.put(RhnWizardAction.STEP_START, wizStep);
}
else if (stepName.equals("second")) {
wizStep.setPrevious("first");
wizStep.setNext("third");
}
else if (stepName.equals("third")) {
wizStep.setPrevious("second");
}
else if (stepName.equals("fourth")) {
wizStep.setPrevious("first");
}
else if (stepName.equals("fifth")) {
wizStep.setPrevious("first");
}
wizardSteps.put(stepName, wizStep);
}
}
private class Profiles implements Listable<KickstartDto> {
/**
* {@inheritDoc}
*/
public List<KickstartDto> getResult(RequestContext ctx) {
Long sid = ctx.getParamAsLong(RequestContext.SID);
User user = ctx.getCurrentUser();
KickstartScheduleCommand cmd = getKickstartScheduleCommand(sid,
user);
DataResult<KickstartDto> profiles = cmd.getKickstartProfiles();
if (profiles.size() == 0) {
addMessage(ctx.getRequest(), "kickstart.schedule.noprofiles");
ctx.getRequest().setAttribute(HAS_PROFILES,
Boolean.FALSE.toString());
}
else {
ctx.getRequest().setAttribute(HAS_PROFILES,
Boolean.TRUE.toString());
}
return profiles;
}
}
/**
* Sets up the proxy information for the wizard.
* its public in this class because we reuse this in SSM
* and only this class knows how to format the name nicely.
* @param ctx the request context needed for user info and
* things to bind to the request
*/
public static void setupProxyInfo(RequestContext ctx) {
List<OrgProxyServer> proxies = SystemManager.
listProxies(ctx.getCurrentUser().getOrg());
if (proxies != null && proxies.size() > 0) {
List<LabelValueBean> formatted = new LinkedList<LabelValueBean>();
formatted.add(lvl10n("kickstart.schedule.default.proxy.jsp", ""));
Map<String, List<String>> cnames = new HashMap<String, List<String>>();
for (OrgProxyServer serv : proxies) {
formatted.add(lv(serv.getName() + " (" + serv.getCheckin() + ")",
serv.getId().toString()));
List<String> proxyCnames =
Config.get().getList(VALID_CNAMES +
serv.getId().toString());
if (!proxyCnames.isEmpty()) {
cnames.put(serv.getId().toString(), proxyCnames);
}
}
ctx.getRequest().setAttribute(HAS_PROXIES, Boolean.TRUE.toString());
ctx.getRequest().setAttribute(PROXIES, formatted);
ctx.getRequest().setAttribute(CNAMES, cnames);
}
else {
ctx.getRequest().setAttribute(HAS_PROXIES, Boolean.FALSE.toString());
}
}
private void setupBondInfo(DynaActionForm form, RequestContext context,
KickstartScheduleCommand cmd) {
Server server = cmd.getServer();
List<NetworkInterface> nics = new LinkedList<NetworkInterface>
(server.getNetworkInterfaces());
if (nics.isEmpty()) {
return;
}
for (Iterator<NetworkInterface> itr = nics.iterator(); itr.hasNext();) {
NetworkInterface nic = itr.next();
if ("127.0.0.1".equals(nic.getIpaddr())) {
itr.remove();
}
}
context.getRequest().setAttribute(ALL_NETWORK_INTERFACES, nics);
if (StringUtils.isBlank(form.getString(BOND_TYPE))) {
form.set(BOND_TYPE, DONT_CREATE_BOND_VALUE);
}
NetworkInterface oldBond = null;
for (NetworkInterface nic : nics) {
if (nic.isBond()) {
oldBond = nic;
break;
}
}
if (oldBond != null) {
if (StringUtils.isBlank(form.getString(BOND_INTERFACE))) {
form.set(BOND_INTERFACE, oldBond.getName());
}
if (StringUtils.isBlank(form.getString(BOND_IP_ADDRESS))) {
form.set(BOND_IP_ADDRESS, oldBond.getIpaddr());
}
if (StringUtils.isBlank(form.getString(BOND_NETMASK))) {
form.set(BOND_NETMASK, oldBond.getNetmask());
}
}
String[] slaves = (String[]) form.get(BOND_SLAVE_INTERFACES);
if (slaves == null || slaves.length == 0) {
List<String> slavesList = new ArrayList<String>();
// if there is a bonded interface on the system
if (!StringUtils.isBlank(form.getString(BOND_INTERFACE))) {
for (NetworkInterface nic : nics) {
// if the nic does not have an IP address it is probably a
// slave to the bond, add it to the default selected list
if (StringUtils.isBlank(nic.getIpaddr())) {
slavesList.add(nic.getName());
}
}
}
form.set(BOND_SLAVE_INTERFACES,
convertToStringArray(slavesList.toArray()));
}
}
/*
* Throwing an error when casting from Object[] to String [], so let's do it
* manually
*/
private String[] convertToStringArray(Object[] objects) {
String[] strings = new String[objects.length];
int i = 0;
for (Object object : objects) {
strings[i] = (String) object;
i++;
}
return strings;
}
private List<NetworkInterface> getPublicNetworkInterfaces(
Server server) {
List<NetworkInterface> nics = new LinkedList<NetworkInterface>(
server.getNetworkInterfaces());
for (Iterator<NetworkInterface> itr = nics.iterator(); itr.hasNext();) {
NetworkInterface nic = itr.next();
if (nic.isDisabled() || "127.0.0.1".equals(nic.getIpaddr())) {
itr.remove();
}
}
return nics;
}
private void setupNetworkInfo(DynaActionForm form, RequestContext context,
KickstartScheduleCommand cmd) {
Server server = cmd.getServer();
List<NetworkInterface> nics = getPublicNetworkInterfaces(server);
if (nics.isEmpty()) {
return;
}
context.getRequest().setAttribute(NETWORK_INTERFACES, nics);
if (StringUtils.isBlank(form.getString(NETWORK_INTERFACE))) {
String defaultInterface = ConfigDefaults.get().
getDefaultKickstartNetworkInterface();
for (NetworkInterface nic : nics) {
if (nic.getName().equals(defaultInterface)) {
form.set(NETWORK_INTERFACE, ConfigDefaults.get().
getDefaultKickstartNetworkInterface());
}
}
if (StringUtils.isBlank(form.getString(NETWORK_INTERFACE))) {
form.set(NETWORK_INTERFACE, server.
findPrimaryNetworkInterface().getName());
}
}
}
/**
* The first step in the wizard
* @param mapping ActionMapping for struts
* @param form DynaActionForm representing the form
* @param ctx RequestContext request context
* @param response HttpServletResponse response object
* @param step WizardStep what step are we on?
*
* @return ActionForward struts action forward
* @throws Exception if something goes amiss
*/
public ActionForward runFirst(ActionMapping mapping, DynaActionForm form,
RequestContext ctx, HttpServletResponse response, WizardStep step)
throws Exception {
log.debug("runFirst");
Long sid = (Long) form.get(RequestContext.SID);
User user = ctx.getCurrentUser();
KickstartScheduleCommand cmd = getKickstartScheduleCommand(sid, user);
Server system = SystemManager.lookupByIdAndUser(sid, user);
if (system.isVirtualGuest() &&
VirtualInstanceFactory.getInstance().getParaVirtType().equals(
system.getVirtualInstance().getType())) {
ctx.getRequest().setAttribute(IS_VIRTUAL_GUEST,
Boolean.TRUE.toString());
ctx.getRequest().setAttribute(VIRT_HOST_IS_REGISTERED,
Boolean.FALSE.toString());
if (system.getVirtualInstance().getHostSystem() != null) {
Long hostSid = system.getVirtualInstance().getHostSystem()
.getId();
ctx.getRequest().setAttribute(VIRT_HOST_IS_REGISTERED,
Boolean.TRUE.toString());
ctx.getRequest().setAttribute(HOST_SID, hostSid);
}
}
else {
ctx.getRequest().setAttribute(IS_VIRTUAL_GUEST,
Boolean.FALSE.toString());
}
addRequestAttributes(ctx, cmd, form);
checkForKickstart(form, cmd, ctx);
setupProxyInfo(ctx);
if (StringUtils.isBlank(form.getString(PROXY_HOST))) {
form.set(PROXY_HOST, "");
}
// create and prepopulate the date picker.
getStrutsDelegate().prepopulateDatePicker(
ctx.getRequest(), form, "date", DatePicker.YEAR_RANGE_POSITIVE);
SdcHelper.ssmCheck(ctx.getRequest(), system.getId(), user);
Map<String, Long> params = new HashMap<String, Long>();
params.put(RequestContext.SID, sid);
ListHelper helper = new ListHelper(new Profiles(), ctx.getRequest(),
params);
helper.execute();
if (!StringUtils.isBlank(form.getString(RequestContext.COBBLER_ID))) {
ListTagHelper.selectRadioValue(ListHelper.LIST,
form.getString(RequestContext.COBBLER_ID), ctx.getRequest());
}
else if (system.getCobblerId() != null) {
//if nothing is selected by the user yet, use the cobbler
// system record to pre-select something.
SystemRecord rec = SystemRecord.lookupById(
CobblerXMLRPCHelper.getConnection(
ConfigDefaults.get().getCobblerAutomatedUser()),
system.getCobblerId());
if (rec != null) {
org.cobbler.Profile profile = rec.getProfile();
if (profile != null) {
ListTagHelper.selectRadioValue(ListHelper.LIST,
profile.getId(), ctx.getRequest());
}
}
}
// display a warning if displaying ppc64le profiles to a ppc system
Channel baseChannel = system.getBaseChannel();
if (baseChannel != null &&
baseChannel.getChannelArch().getLabel().equals("channel-ppc")) {
List<KickstartDto> profiles = helper.getDataSet();
for (KickstartDto profile : profiles) {
KickstartableTree tree = KickstartFactory.findTreeById(profile
.getKstreeId(), user.getOrg().getId());
if (tree.getChannel().getChannelArch().getLabel()
.equals("channel-ppc64le")) {
addMessage(ctx.getRequest(), "kickstart.schedule.ppc64lewarning");
break;
}
}
}
ActionForward retval = mapping.findForward("first");
return retval;
}
/**
* The second step in the wizard
* @param mapping ActionMapping for struts
* @param form DynaActionForm representing the form
* @param ctx RequestContext request context
* @param response HttpServletResponse response object
* @param step WizardStep what step are we on?
*
* @return ActionForward struts action forward
* @throws Exception if something goes amiss
*/
public ActionForward runSecond(ActionMapping mapping, DynaActionForm form,
RequestContext ctx, HttpServletResponse response, WizardStep step)
throws Exception {
log.debug("runSecond");
if (!StringUtils.isBlank(form.getString(HIDDEN_BOND_SLAVE_INTERFACES))) {
form.set(BOND_SLAVE_INTERFACES,
form.getString(HIDDEN_BOND_SLAVE_INTERFACES).split(","));
}
Long sid = (Long) form.get(RequestContext.SID);
User user = ctx.getCurrentUser();
if (!validateFirstSelections(form, ctx)) {
return runFirst(mapping, form, ctx, response, step);
}
KickstartScheduleCommand cmd = getScheduleCommand(form, ctx, null, null);
checkForKickstart(form, cmd, ctx);
addRequestAttributes(ctx, cmd, form);
if (!cmd.isCobblerOnly()) {
List<ProfileDto> packageProfiles = cmd.getProfiles();
form.set(SYNCH_PACKAGES, packageProfiles);
List<Map<String, Object>> systemProfiles = cmd.getCompatibleSystems();
form.set(SYNCH_SYSTEMS, systemProfiles);
// Disable the package/system sync radio buttons if no profiles are
// available:
String syncPackageDisabled = "false";
if (packageProfiles.size() == 0) {
syncPackageDisabled = "true";
}
String syncSystemDisabled = "false";
if (systemProfiles.size() == 0) {
syncSystemDisabled = "true";
}
ctx.getRequest()
.setAttribute(SYNC_PACKAGE_DISABED, syncPackageDisabled);
ctx.getRequest().setAttribute(SYNC_SYSTEM_DISABLED, syncSystemDisabled);
if (StringUtils.isEmpty(form.getString(TARGET_PROFILE_TYPE))) {
form.set(TARGET_PROFILE_TYPE,
KickstartScheduleCommand.TARGET_PROFILE_TYPE_NONE);
}
}
else {
ctx.getRequest().setAttribute(COBBLER_ONLY_PROFILE, Boolean.TRUE);
}
if (StringUtils.isEmpty(form.getString(KERNEL_PARAMS_TYPE))) {
form.set(KERNEL_PARAMS_TYPE, KERNEL_PARAMS_DISTRO);
}
if (StringUtils.isEmpty(form.getString(POST_KERNEL_PARAMS_TYPE))) {
form.set(POST_KERNEL_PARAMS_TYPE, KERNEL_PARAMS_DISTRO);
}
SdcHelper.ssmCheck(ctx.getRequest(), sid, user);
return mapping.findForward("second");
}
protected void addRequestAttributes(RequestContext ctx,
KickstartScheduleCommand cmd, DynaActionForm form) {
ctx.getRequest().setAttribute(RequestContext.SYSTEM, cmd.getServer());
ctx.getRequest()
.setAttribute(RequestContext.KICKSTART, cmd.getKsdata());
if (cmd.getKsdata() != null) {
ctx.getRequest().setAttribute("profile", cmd.getKsdata());
ctx.getRequest().setAttribute("distro", cmd.getKsdata().getTree());
CobblerConnection con = CobblerXMLRPCHelper.
getConnection(ctx.getCurrentUser());
Distro distro = Distro.lookupById(con,
cmd.getKsdata().getTree().getCobblerId());
ctx.getRequest().setAttribute("distro_kernel_params",
distro.getKernelOptionsString());
ctx.getRequest().setAttribute("distro_post_kernel_params",
distro.getKernelPostOptionsString());
org.cobbler.Profile profile = org.cobbler.Profile.
lookupById(con, cmd.getKsdata().getCobblerId());
ctx.getRequest().setAttribute("profile_kernel_params",
profile.getKernelOptionsString());
ctx.getRequest().setAttribute("profile_post_kernel_params",
profile.getKernelPostOptionsString());
if (cmd.getServer().getCobblerId() != null) {
SystemRecord rec = SystemRecord.
lookupById(con, cmd.getServer().getCobblerId());
if (rec != null && rec.getProfile() != null &&
profile.getName().equals(rec.getProfile().getName())) {
if (StringUtils.isBlank(form.getString(KERNEL_PARAMS_TYPE))) {
form.set(KERNEL_PARAMS_TYPE, KERNEL_PARAMS_CUSTOM);
form.set(KERNEL_PARAMS, rec.getKernelOptionsString());
}
if (StringUtils.isBlank(form.getString(POST_KERNEL_PARAMS_TYPE))) {
form.set(POST_KERNEL_PARAMS_TYPE, KERNEL_PARAMS_CUSTOM);
form.set(POST_KERNEL_PARAMS, rec.getKernelPostOptionsString());
}
}
}
}
setupNetworkInfo(form, ctx, cmd);
setupBondInfo(form, ctx, cmd);
}
/**
* The third step in the wizard
* @param mapping ActionMapping for struts
* @param form DynaActionForm representing the form
* @param ctx RequestContext request context
* @param response HttpServletResponse response object
* @param step WizardStep what step are we on?
*
* @return ActionForward struts action forward
* @throws Exception if something goes amiss
*/
public ActionForward runThird(ActionMapping mapping, DynaActionForm form,
RequestContext ctx, HttpServletResponse response, WizardStep step)
throws Exception {
log.debug("runThird");
if (!validateBondSelections(form, ctx)) {
return runSecond(mapping, form, ctx, response, step);
}
if (!validateFirstSelections(form, ctx)) {
return runFirst(mapping, form, ctx, response, step);
}
String scheduleAsap = form.getString("scheduleAsap");
Date scheduleTime = null;
if (scheduleAsap != null && scheduleAsap.equals("false")) {
scheduleTime = getStrutsDelegate().readDatePicker(form, "date",
DatePicker.YEAR_RANGE_POSITIVE);
}
else {
scheduleTime = new Date();
}
KickstartHelper helper = new KickstartHelper(ctx.getRequest());
KickstartScheduleCommand cmd = getScheduleCommand(form, ctx,
scheduleTime, helper.getKickstartHost());
if (showDiskWarning(cmd.getKsdata(), form)) {
form.set(NEXT_ACTION, "third");
addRequestAttributes(ctx, cmd, form);
return mapping.findForward("fifth");
}
cmd.setNetworkDevice(form.getString(NETWORK_TYPE),
form.getString(NETWORK_INTERFACE));
if (CREATE_BOND_VALUE.equals(form.getString(BOND_TYPE))) {
cmd.setCreateBond(true);
cmd.setBondInterface(form.getString(BOND_INTERFACE));
cmd.setBondOptions(form.getString(BOND_OPTIONS));
String[] slaves = (String[]) form.get(BOND_SLAVE_INTERFACES);
List<String> tmp = new ArrayList<String>();
for (String slave : slaves) {
tmp.add(slave);
}
cmd.setBondSlaveInterfaces(tmp);
if (STATIC_BOND_VALUE.equals(form.getString(BOND_STATIC))) {
cmd.setBondDhcp(false);
cmd.setBondAddress(form.getString(BOND_IP_ADDRESS));
cmd.setBondNetmask(form.getString(BOND_NETMASK));
cmd.setBondGateway(form.getString(BOND_GATEWAY));
}
else {
cmd.setBondDhcp(true);
}
}
if (form.getString(USE_IPV6_GATEWAY).equals("1")) {
cmd.setIpv6Gateway();
}
cmd.setKernelOptions(parseKernelOptions(form, ctx.getRequest(),
form.getString(RequestContext.COBBLER_ID), false));
cmd.setPostKernelOptions(parseKernelOptions(form, ctx.getRequest(),
form.getString(RequestContext.COBBLER_ID), true));
if (!cmd.isCobblerOnly()) {
// now setup system/package profiles for kickstart to sync
Profile pkgProfile = cmd.getKsdata().getKickstartDefaults()
.getProfile();
Long packageProfileId = pkgProfile != null ? pkgProfile.getId() : null;
// if user did not override package profile, then grab from ks
// profile if avail
if (packageProfileId != null) {
cmd.setProfileId(packageProfileId);
cmd.setProfileType(KickstartScheduleCommand.TARGET_PROFILE_TYPE_PACKAGE);
}
else {
/*
* NOTE: these values are essentially ignored if user did not go
* through advanced config and there is no package profile to
* sync in the kickstart profile
*/
cmd.setProfileType(form.getString(TARGET_PROFILE_TYPE));
cmd.setServerProfileId((Long) form.get("targetServerProfile"));
cmd.setProfileId((Long) form.get("targetProfile"));
}
}
storeProxyInfo(form, ctx, cmd);
// Store the new KickstartSession to the DB.
ValidatorError ve = cmd.store();
if (ve != null) {
ActionErrors errors = RhnValidationHelper
.validatorErrorToActionErrors(ve);
if (!errors.isEmpty()) {
getStrutsDelegate().saveMessages(ctx.getRequest(), errors);
return runFirst(mapping, form, ctx, response, step);
}
}
Map<String, Object> params = new HashMap<String, Object>();
params.put(RequestContext.SID, form.get(RequestContext.SID));
if (cmd.isCobblerOnly()) {
createSuccessMessage(ctx.getRequest(),
"kickstart.cobbler.schedule.success", LocalizationService
.getInstance().formatDate(scheduleTime));
return getStrutsDelegate().forwardParams(
mapping.findForward("cobbler-success"), params);
}
createSuccessMessage(ctx.getRequest(), "kickstart.schedule.success",
LocalizationService.getInstance().formatDate(scheduleTime));
return getStrutsDelegate().forwardParams(
mapping.findForward("success"), params);
}
/**
* Setup the system for provisioning with cobbler.
*
* @param mapping ActionMapping for struts
* @param form DynaActionForm representing the form
* @param ctx RequestContext request context
* @param response HttpServletResponse response object
* @param step WizardStep what step are we on?
*
* @return ActionForward struts action forward
* @throws Exception if something goes amiss
*/
public ActionForward runFourth(ActionMapping mapping, DynaActionForm form,
RequestContext ctx, HttpServletResponse response, WizardStep step)
throws Exception {
log.debug("runFourth");
if (!validateFirstSelections(form, ctx)) {
return runFirst(mapping, form, ctx, response, step);
}
Long sid = (Long) form.get(RequestContext.SID);
String cobblerId = form.getString(RequestContext.COBBLER_ID);
log.debug("runFourth.cobblerId: " + cobblerId);
User user = ctx.getCurrentUser();
Server server = SystemManager.lookupByIdAndUser(sid, user);
Map<String, Object> params = new HashMap<String, Object>();
params.put(RequestContext.SID, sid);
log.debug("Creating cobbler system record");
org.cobbler.Profile profile = org.cobbler.Profile.lookupById(
CobblerXMLRPCHelper.getConnection(user), cobblerId);
KickstartData data = KickstartFactory.lookupKickstartDataByCobblerIdAndOrg(
user.getOrg(), profile.getUid());
if (showDiskWarning(data, form)) {
form.set(NEXT_ACTION, "fourth");
ctx.getRequest().setAttribute(RequestContext.SYSTEM, server);
return mapping.findForward("fifth");
}
CobblerSystemCreateCommand cmd = new CobblerSystemCreateCommand(server,
profile.getName(), data);
cmd.store();
log.debug("cobbler system record created.");
String[] args = new String[2];
args[0] = server.getName();
args[1] = profile.getName();
createMessage(ctx.getRequest(), "kickstart.schedule.cobblercreate",
args);
return getStrutsDelegate().forwardParams(
mapping.findForward("cobbler-success"), params);
}
/**
* Returns the kickstart schedule command
* @param form the dyna aciton form
* @param ctx the request context
* @param scheduleTime the schedule time
* @param host the host url.
* @return the Ks schedule command
*/
protected KickstartScheduleCommand getScheduleCommand(DynaActionForm form,
RequestContext ctx, Date scheduleTime, String host) {
String cobblerId = form.getString(RequestContext.COBBLER_ID);
User user = ctx.getCurrentUser();
KickstartScheduleCommand cmd;
KickstartData data = KickstartFactory
.lookupKickstartDataByCobblerIdAndOrg(user.getOrg(), cobblerId);
if (data != null) {
cmd = new KickstartScheduleCommand((Long) form
.get(RequestContext.SID), data, ctx.getCurrentUser(),
scheduleTime, host);
}
else {
org.cobbler.Profile profile = org.cobbler.Profile.lookupById(
CobblerXMLRPCHelper.getConnection(user), cobblerId);
cmd = KickstartScheduleCommand.createCobblerScheduleCommand(
(Long) form.get(RequestContext.SID), profile.getName(),
user, scheduleTime, host);
}
return cmd;
}
/**
* @param form the form containing the proxy info
* @param ctx the request context associated to this request
* @param cmd the kicktstart command to which the proxy info will be
* copied..
*/
protected void storeProxyInfo(DynaActionForm form, RequestContext ctx,
KickstartScheduleCommand cmd) {
// if we need to go through a proxy, do it here.
String phost = form.getString(PROXY_HOST);
String phostCname = form.getString(PROXY_HOST_CNAME);
if (!StringUtils.isEmpty(phostCname)) {
cmd.setProxyHost(phostCname);
}
else if (!StringUtils.isEmpty(phost)) {
cmd.setProxy(SystemManager.lookupByIdAndOrg(new Long(phost), ctx
.getCurrentUser().getOrg()));
}
}
protected boolean validateBondSelections(DynaActionForm form,
RequestContext ctx) {
if (!StringUtils.isBlank(form.getString(HIDDEN_BOND_SLAVE_INTERFACES))) {
form.set(BOND_SLAVE_INTERFACES,
form.getString(HIDDEN_BOND_SLAVE_INTERFACES).split(","));
}
String[] slaves = (String[]) form.get(BOND_SLAVE_INTERFACES);
ActionErrors errors = new ActionErrors();
// if we are trying to create a bond but have not specified a name or at
// least one slave interface
if (form.getString(BOND_TYPE).equals(CREATE_BOND_VALUE) &&
(StringUtils.isBlank(form.getString(BOND_INTERFACE)) ||
slaves.length < 1 || StringUtils.isBlank(slaves[0]))) {
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
"kickstart.bond.not.defined.jsp"));
}
final String ipv4addressPattern = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
/*
* The IPv6 address regex was created by Stephen Ryan at Dartware
* and taken from this forum: http://forums.intermapper.com/viewtopic.php?t=452
* It is licenced under a Creative Commons Attribution-ShareAlike 3.0 Unported
* License. We can freely use it in (even in commercial products) as long as
* we attribute its creation to him, so don't remove this message.
*/
final String ipv6addressPattern = "^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-" +
"F]{1,4}::?){0,5}|([0-9A-F]{1,4}:){6})(\\2([0-9A-F]{1,4}(::?|$))" +
"{0,2}|((25[0-5]|(2[0-4]|1\\d|[1-9])?\\d)(\\.|$)){4}|[0-9A-F]{1," +
"4}:[0-9A-F]{1,4})(?<![^:]:|\\.)\\z";
if (form.getString(BOND_STATIC).equals(STATIC_BOND_VALUE)) {
String address = form.getString(BOND_IP_ADDRESS);
String netmask = form.getString(BOND_NETMASK);
String gateway = form.getString(BOND_GATEWAY);
if (!address.matches(ipv4addressPattern) &&
!address.matches(ipv6addressPattern)) {
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
"kickstart.bond.bad.ip.address.jsp"));
}
if (!netmask.matches(ipv4addressPattern) &&
!netmask.matches(ipv6addressPattern)) {
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
"kickstart.bond.bad.netmask.jsp"));
}
if (!gateway.matches(ipv4addressPattern) &&
!gateway.matches(ipv6addressPattern)) {
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
"kickstart.bond.bad.ip.address.jsp"));
}
}
if (errors.size() > 0) {
addErrors(ctx.getRequest(), errors);
return false;
}
return true;
}
protected boolean validateFirstSelections(DynaActionForm form,
RequestContext ctx) {
String cobblerId = ListTagHelper.getRadioSelection(ListHelper.LIST,
ctx.getRequest());
if (StringUtils.isBlank(cobblerId)) {
cobblerId = ctx.getParam(RequestContext.COBBLER_ID, true);
}
boolean retval = false;
form.set(RequestContext.COBBLER_ID, cobblerId);
ctx.getRequest().setAttribute(RequestContext.COBBLER_ID, cobblerId);
if (form.get("scheduleAsap") != null) {
retval = true;
}
else if (form.get(RequestContext.COBBLER_ID) != null) {
return true;
}
return retval;
}
/*
* If the user is going to clear all partitions from all drives we need to ask
* him if he's sure first.
*/
protected boolean showDiskWarning(KickstartData data, DynaActionForm form) {
Set<KickstartCommand> commands = data.getOptions();
boolean containsClearpartCommand = false;
for (KickstartCommand command : commands) {
if (command.getCommandName() != null &&
command.getCommandName().getName() != null &&
command.getCommandName().getName().equals("clearpart")) {
if (command.getArguments() != null &&
command.getArguments().contains("--drives")) {
return false;
}
containsClearpartCommand = true;
break;
}
continue;
}
String diskOption = form.getString(DESTROY_DISKS);
if (!containsClearpartCommand || (diskOption != null &&
diskOption.equals("true"))) {
return false;
}
return true;
}
private void checkForKickstart(DynaActionForm form,
KickstartScheduleCommand cmd, RequestContext ctx) {
if (ActionFactory.doesServerHaveKickstartScheduled((Long) form
.get(RequestContext.SID))) {
String[] params = { cmd.getServer().getName() };
getStrutsDelegate().saveMessage(
"kickstart.schedule.already.scheduled.jsp", params,
ctx.getRequest());
}
}
protected KickstartScheduleCommand getKickstartScheduleCommand(Long sid,
User currentUser) {
return new KickstartScheduleCommand(sid, currentUser);
}
/**
* Parses the kernel options or Post kernel options
* from the given form. Called after the advanced options page
* is typically set..
* This is a handy method used in both SSM and SDC KS scheduling.
* @param form the kickstartScheduleWizardForm that holds the form fields.
* @param request the servlet request
* @param profileCobblerId the cobbler profile id
* @param isPost true if caller is interested in getting the
* post kernel options and not the pre.
* @return the kernel options selected by the user.
*/
public static String parseKernelOptions(DynaActionForm form,
HttpServletRequest request,
String profileCobblerId,
boolean isPost) {
RequestContext context = new RequestContext(request);
String typeKey = !isPost ? KERNEL_PARAMS_TYPE : POST_KERNEL_PARAMS_TYPE;
String customKey = !isPost ? KERNEL_PARAMS : POST_KERNEL_PARAMS;
String type = form.getString(typeKey);
return parseKernelOptions(form.getString(customKey), type, profileCobblerId,
isPost, context.getCurrentUser());
}
/**
* Parses the kernel options or Post kernel options
* from the given set of params
* This is a handy method used in both SSM and SDC KS scheduling.
* @param customOptions the kickstartScheduleWizardForm that holds the form fields.
* @param paramsType either KERNEL_PARAMS_CUSTOM _DISTRO or _PROFILE
* @param cobblerId the cobbler profile id
* @param isPost true if caller is interested in getting the
* post kernel options and not the pre.
* @param user the user doing the request
* @return the kernel options selected by the user.
*/
public static String parseKernelOptions(String customOptions,
String paramsType,
String cobblerId,
boolean isPost, User user) {
CobblerConnection con = CobblerXMLRPCHelper.
getConnection(user);
if (KERNEL_PARAMS_CUSTOM.equals(paramsType)) {
return customOptions;
}
org.cobbler.Profile profile = org.cobbler.Profile.lookupById(con,
cobblerId);
CobblerObject ret = profile;
if (KERNEL_PARAMS_DISTRO.equals(paramsType)) {
ret = profile.getDistro();
}
if (!isPost) {
return ret.getKernelOptionsString();
}
return ret.getKernelPostOptionsString();
}
}