/**
* Copyright (c) 2014 SUSE LLC
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
/**
* Copyright (c) 2014 Red Hat, Inc.
*/
package com.redhat.rhn.frontend.xmlrpc.chain;
import com.redhat.rhn.common.util.StringUtil;
import com.redhat.rhn.domain.action.ActionChain;
import com.redhat.rhn.domain.action.ActionChainEntry;
import com.redhat.rhn.domain.action.ActionChainFactory;
import com.redhat.rhn.domain.action.ActionFactory;
import com.redhat.rhn.domain.action.script.ScriptActionDetails;
import com.redhat.rhn.domain.server.Server;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.frontend.xmlrpc.BaseHandler;
import com.redhat.rhn.frontend.xmlrpc.InvalidParameterException;
import com.redhat.rhn.frontend.xmlrpc.NoSuchActionException;
import com.redhat.rhn.manager.action.ActionChainManager;
import com.redhat.rhn.manager.action.ActionManager;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.collections.CollectionUtils;
/**
* @xmlrpc.namespace actionchain
* @xmlrpc.doc Provides the namespace for the Action Chain methods.
*/
public class ActionChainHandler extends BaseHandler {
private final ActionChainRPCCommon acUtil;
/**
* Parameters collector.
*/
public ActionChainHandler() {
this.acUtil = new ActionChainRPCCommon();
}
/**
* List currently available action chains.
*
* @param loggedInUser The current user
* @return list of action chains.
*
* @xmlrpc.doc List currently available action chains.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.returntype #array()
* #struct("chain")
* #prop_desc("string", "label", "Label of an Action Chain")
* #prop_desc("string", "entrycount",
* "Number of entries in the Action Chain")
* #struct_end()
* #array_end()
*/
public List<Map<String, Object>> listChains(User loggedInUser) {
List<Map<String, Object>> chains = new ArrayList<Map<String, Object>>();
for (ActionChain actionChain : ActionChainFactory.getActionChains(loggedInUser)) {
Map<String, Object> info = new HashMap<String, Object>();
info.put("label", actionChain.getLabel());
info.put("entrycount", actionChain.getEntries().size());
chains.add(info);
}
return chains;
}
/**
* List all actions in the particular Action Chain.
*
* @param loggedInUser The current user
* @param chainLabel The label of the Action Chain.
* @return List of entries in the particular action chain, if any.
*
* @xmlrpc.doc List all actions in the particular Action Chain.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.returntype #array()
* #struct("entry")
* #prop_desc("int", "id", "Action ID")
* #prop_desc("string", "label", "Label of an Action")
* #prop_desc("string", "created", "Created date/time")
* #prop_desc("string", "earliest",
* "Earliest scheduled date/time")
* #prop_desc("string", "type", "Type of the action")
* #prop_desc("string", "modified", "Modified date/time")
* #prop_desc("string", "cuid", "Creator UID")
* #struct_end()
* #array_end()
*/
public List<Map<String, Object>> listChainActions(User loggedInUser,
String chainLabel) {
List<Map<String, Object>> entries = new ArrayList<Map<String, Object>>();
ActionChain chain = this.acUtil.getActionChainByLabel(loggedInUser, chainLabel);
if (chain.getEntries() != null && !chain.getEntries().isEmpty()) {
for (ActionChainEntry entry : chain.getEntries()) {
String label = entry.getAction().getName();
Map<String, Object> info = new HashMap<String, Object>();
info.put("id", entry.getAction().getId());
info.put("label", StringUtil.nullOrValue(label) == null ?
entry.getAction().getActionType().getName() :
label);
info.put("created", entry.getAction().getCreated());
info.put("earliest", entry.getAction().getEarliestAction());
info.put("type", entry.getAction().getActionType().getName());
info.put("modified", entry.getAction().getModified());
info.put("cuid", entry.getAction().getSchedulerUser().getLogin());
entries.add(info);
}
}
return entries;
}
/**
* Remove an action from the Action Chain.
*
* @param loggedInUser The current user
* @param chainLabel The label of the Action Chain.
* @param actionId Action ID.
* @return 1 if successful, exception otherwise
*
* @xmlrpc.doc Remove an action from an Action Chain.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.param #param_desc("int", "actionId", "Action ID")
* @xmlrpc.returntype #return_int_success()
*/
public Integer removeAction(User loggedInUser,
String chainLabel,
Integer actionId) {
ActionChain chain = this.acUtil.getActionChainByLabel(loggedInUser, chainLabel);
for (ActionChainEntry entry : chain.getEntries()) {
if (entry.getAction().getId().equals(Long.valueOf(actionId))) {
ActionChainFactory.removeActionChainEntry(chain, entry);
return BaseHandler.VALID;
}
}
throw new NoSuchActionException("ID: " + actionId);
}
/**
* Remove Action Chains by label.
*
* @param loggedInUser The current user
* @param chainLabel Action Chain label.
* @return 1 if successful, exception otherwise
*
* @xmlrpc.doc Delete action chain by label.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.returntype #return_int_success()
*/
public Integer deleteChain(User loggedInUser, String chainLabel) {
ActionChainFactory.delete(
this.acUtil.getActionChainByLabel(loggedInUser, chainLabel));
return BaseHandler.VALID;
}
/**
* Create an Action Chain.
*
* @param loggedInUser The current user
* @param chainLabel Label of the action chain
* @return id of the created action chain
*
* @xmlrpc.doc Create an Action Chain.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.returntype int actionId - The ID of the created action chain
*/
public Integer createChain(User loggedInUser,
String chainLabel) {
if (StringUtil.nullOrValue(chainLabel) == null) {
throw new InvalidParameterException("Chain label is missing");
}
if (ActionChainFactory.getActionChain(loggedInUser, chainLabel) != null) {
throw new InvalidParameterException(
"Another Action Chain with the same label already exists");
}
return ActionChainFactory.createActionChain(
chainLabel, loggedInUser).getId().intValue();
}
/**
* Schedule system reboot.
*
* @param loggedInUser The current user
* @param serverId Server ID.
* @param chainLabel Label of the action chain
* @return list of action ids, exception thrown otherwise
*
* @xmlrpc.doc Add system reboot to an Action Chain.
* @xmlrpc.param #param_desc("string", "sessionKey",
* "Session token, issued at login")
* @xmlrpc.param #param("int", "serverId")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.returntype int actionId - The action id of the scheduled action
*/
public Integer addSystemReboot(User loggedInUser,
Integer serverId,
String chainLabel) {
return ActionChainManager.scheduleRebootAction(
loggedInUser, this.acUtil.getServerById(serverId, loggedInUser),
new Date(), this.acUtil.getActionChainByLabel(loggedInUser, chainLabel)
).getId().intValue();
}
/**
* Schedule Errata update.
*
* @param loggedInUser The current user
* @param serverId Server ID.
* @param errataIds a list of erratas IDs
* @param chainLabel Label of the action chain
* @return action id if successful, exception otherwise
*
* @xmlrpc.doc Adds Errata update to an Action Chain.
* @xmlrpc.param #param_desc("string", "sessionKey",
* "Session token, issued at login")
* @xmlrpc.param #param_desc("int", "serverId", "System ID")
* @xmlrpc.param #array_single("int", "Errata ID")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.returntype int actionId - The action id of the scheduled action
*/
public Integer addErrataUpdate(User loggedInUser,
Integer serverId,
List<Integer> errataIds,
String chainLabel) {
if (errataIds.isEmpty()) {
throw new InvalidParameterException("No specified Erratas.");
}
return ActionChainManager.scheduleErrataUpdate(
loggedInUser, this.acUtil.getServerById(serverId, loggedInUser), errataIds,
new Date(), this.acUtil.getActionChainByLabel(loggedInUser, chainLabel)
).getId().intValue();
}
/**
* Adds an action to remove installed packages on the system.
*
* @param loggedInUser The current user
* @param serverId System ID
* @param packages List of packages
* @param chainLabel Label of the action chain
* @return list of action ids, exception thrown otherwise
*
* @xmlrpc.doc Adds an action to remove installed packages on the system to an Action
* Chain.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("int", "serverId", "System ID")
* @xmlrpc.param #array_single("int", "Package ID")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.returntype int actionId - The action id of the scheduled action or exception
*/
public Integer addPackageRemoval(User loggedInUser,
Integer serverId,
List<Integer> packages,
String chainLabel) {
if (packages.isEmpty()) {
throw new InvalidParameterException("No specified packages.");
}
return ActionChainManager.schedulePackageRemoval(loggedInUser,
this.acUtil.getServerById(serverId, loggedInUser),
this.acUtil.resolvePackages(packages, loggedInUser),
new Date(),
this.acUtil.getActionChainByLabel(loggedInUser, chainLabel))
.getId().intValue();
}
/**
* Schedule package installation to an Action Chain.
*
* @param loggedInUser The current user
* @param serverId System ID.
* @param packages List of packages.
* @param chainLabel Label of the Action Chain.
* @return True or false in XML-RPC representation: 1 or 0 respectively.
*
* @xmlrpc.doc Adds package installation action to an Action Chain.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("int", "serverId", "System ID")
* @xmlrpc.param #array_single("int", "Package ID")
* @xmlrpc.param #param("string", "chainLabel")
* @xmlrpc.returntype #return_int_success()
*/
public Integer addPackageInstall(User loggedInUser,
Integer serverId,
List<Integer> packages,
String chainLabel) {
if (packages.isEmpty()) {
throw new InvalidParameterException("No specified packages.");
}
return ActionChainManager.schedulePackageInstall(loggedInUser,
this.acUtil.getServerById(serverId, loggedInUser),
this.acUtil.resolvePackages(packages, loggedInUser), new Date(),
this.acUtil.getActionChainByLabel(loggedInUser, chainLabel)
).getId().intValue();
}
/**
* Adds an action to verify installed packages on the system.
*
* @param loggedInUser The current user
* @param serverId System ID
* @param packages List of packages
* @param chainLabel Label of the action chain
* @return True or false in XML-RPC representation (1 or 0 respectively)
*
* @xmlrpc.doc Adds an action to verify installed packages on the system to an Action
* Chain.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("int", "serverId", "System ID")
* @xmlrpc.param #array_single("int", "packageId")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.returntype #return_int_success()
*/
public Integer addPackageVerify(User loggedInUser,
Integer serverId,
List<Integer> packages,
String chainLabel) {
if (packages.isEmpty()) {
throw new InvalidParameterException("No specified packages.");
}
Server server = this.acUtil.getServerById(serverId, loggedInUser);
return ActionChainManager.schedulePackageVerify(
loggedInUser, server, this.acUtil.resolvePackages(packages, loggedInUser),
new Date(), this.acUtil.getActionChainByLabel(loggedInUser, chainLabel)
).getId().intValue();
}
/**
* Adds an action to upgrade installed packages on the system.
*
* @param loggedInUser The current user
* @param serverId System ID
* @param packages List of packages
* @param chainLabel Label of the action chain
* @return True or false in XML-RPC representation (1 or 0 respectively)
*
* @xmlrpc.doc Adds an action to upgrade installed packages on the system to an Action
* Chain.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("int", "serverId", "System ID")
* @xmlrpc.param #array_single("int", "packageId")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.returntype int actionId - The id of the action or throw an exception
*/
public int addPackageUpgrade(User loggedInUser,
Integer serverId,
List<Integer> packages,
String chainLabel) {
if (packages.isEmpty()) {
throw new InvalidParameterException("No specified packages.");
}
Server server = this.acUtil.getServerById(serverId, loggedInUser);
return ActionChainManager.schedulePackageUpgrade(
loggedInUser, server, this.acUtil.resolvePackages(packages, loggedInUser),
new Date(),
this.acUtil.getActionChainByLabel(loggedInUser, chainLabel))
.getId().intValue();
}
/**
* Add a remote command as a script.
*
* @param loggedInUser The current user
* @param serverId System ID
* @param chainLabel Label of the action chain.
* @param uid User ID on the remote system.
* @param scriptBody Base64 encoded script.
* @param gid Group ID on the remote system.
* @param timeout Timeout
* @return True or false in XML-RPC representation (1 or 0 respectively)
*
* @xmlrpc.doc Add an action to run a script to an Action Chain.
* NOTE: The script body must be Base64 encoded!
*
* @xmlrpc.param #param_desc("string", "sessionKey",
* "Session token, issued at login")
* @xmlrpc.param #param_desc("int", "serverId", "System ID")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.param #param_desc("string", "uid", "User ID on the particular system")
* @xmlrpc.param #param_desc("string", "gid", "Group ID on the particular system")
* @xmlrpc.param #param_desc("int", "timeout", "Timeout")
* @xmlrpc.param #param_desc("string", "scriptBodyBase64", "Base64 encoded script body")
* @xmlrpc.returntype int actionId - The id of the action or throw an
* exception
*/
public Integer addScriptRun(User loggedInUser, Integer serverId, String chainLabel,
String uid, String gid, Integer timeout, String scriptBody) {
List<Long> systems = new ArrayList<Long>();
systems.add((long) serverId);
ScriptActionDetails script = ActionManager.createScript(
uid, gid, (long) timeout, new String(
DatatypeConverter.parseBase64Binary(scriptBody)));
return ActionChainManager.scheduleScriptRuns(
loggedInUser, systems, null, script, new Date(),
this.acUtil.getActionChainByLabel(loggedInUser, chainLabel)
).iterator().next().getId().intValue();
}
/**
* Schedule action chain.
*
* @param loggedInUser The current user
* @param chainLabel Label of the action chain
* @param date Earliest date
* @return 1 if successful, exception otherwise
*
* @xmlrpc.doc Schedule the Action Chain so that its actions will actually occur.
* @xmlrpc.param #param_desc("string", "sessionKey",
* "Session token, issued at login")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.param #param("dateTime.iso8601", "Earliest date")
* @xmlrpc.returntype #return_int_success()
*/
public Integer scheduleChain(User loggedInUser, String chainLabel, Date date) {
ActionChainFactory.schedule(
this.acUtil.getActionChainByLabel(loggedInUser, chainLabel), date);
return BaseHandler.VALID;
}
/**
* Deploy configuration.
*
* @param loggedInUser The current user
* @param chainLabel Label of the action chain
* @param serverId System ID
* @param revisions List of configuration revisions.
* @return 1 if successful, exception otherwise
*
* @xmlrpc.doc Adds an action to deploy a configuration file to an Action Chain.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("string", "chainLabel", "Label of the chain")
* @xmlrpc.param #param_desc("int", "System ID", "System ID")
* @xmlrpc.param #array_single("int", "Revision ID")
* @xmlrpc.returntype #return_int_success()
*/
@SuppressWarnings("unchecked")
public Integer addConfigurationDeployment(User loggedInUser,
String chainLabel,
Integer serverId,
List<Integer> revisions) {
if (revisions.isEmpty()) {
throw new InvalidParameterException("At least one revision should be given.");
}
List<Long> server = new ArrayList<Long>();
server.add(serverId.longValue());
ActionChainManager.createConfigActions(loggedInUser,
CollectionUtils.collect(revisions,
new ActionChainRPCCommon.IntegerToLongTransformer()), server,
ActionFactory.TYPE_CONFIGFILES_DEPLOY,
new Date(), this.acUtil.getActionChainByLabel(loggedInUser, chainLabel));
return BaseHandler.VALID;
}
/**
* Rename Action Chain.
*
* @param loggedInUser The current user
* @param previousLabel Previous (existing) label of the Action Chain
* @param newLabel New (desired) label of the Action Chain
* @return 1 if successful, exception otherwise
*
* @xmlrpc.doc Rename an Action Chain.
* @xmlrpc.param #param_desc("string", "sessionKey", "Session token, issued at login")
* @xmlrpc.param #param_desc("string", "previousLabel", "Previous chain label")
* @xmlrpc.param #param_desc("string", "newLabel", "New chain label")
* @xmlrpc.returntype #return_int_success()
*/
public Integer renameChain(User loggedInUser,
String previousLabel,
String newLabel) {
if (previousLabel.equals(newLabel)) {
throw new InvalidParameterException("New label of the Action Chain should " +
"not be the same as previous!");
}
else if (previousLabel.isEmpty()) {
throw new InvalidParameterException("Previous label cannot be empty.");
}
else if (newLabel.isEmpty()) {
throw new InvalidParameterException("New label cannot be empty.");
}
if (ActionChainFactory.getActionChain(loggedInUser, newLabel) != null) {
throw new InvalidParameterException(
"Another Action Chain with the same label already exists");
}
this.acUtil.getActionChainByLabel(loggedInUser, previousLabel).setLabel(newLabel);
return BaseHandler.VALID;
}
}