/** * 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.xmlrpc.system.config; import com.redhat.rhn.common.db.datasource.DataResult; import com.redhat.rhn.domain.config.ConfigChannel; import com.redhat.rhn.domain.config.ConfigChannelListProcessor; import com.redhat.rhn.domain.config.ConfigChannelType; import com.redhat.rhn.domain.config.ConfigFile; import com.redhat.rhn.domain.config.ConfigFileType; import com.redhat.rhn.domain.config.ConfigRevision; import com.redhat.rhn.domain.server.Server; import com.redhat.rhn.domain.user.User; import com.redhat.rhn.frontend.dto.ConfigFileDto; import com.redhat.rhn.frontend.dto.ConfigFileNameDto; import com.redhat.rhn.frontend.xmlrpc.BaseHandler; import com.redhat.rhn.frontend.xmlrpc.NoSuchConfigFilePathException; import com.redhat.rhn.frontend.xmlrpc.configchannel.XmlRpcConfigChannelHelper; import com.redhat.rhn.frontend.xmlrpc.serializer.ConfigFileNameDtoSerializer; import com.redhat.rhn.frontend.xmlrpc.serializer.ConfigRevisionSerializer; import com.redhat.rhn.frontend.xmlrpc.system.XmlRpcSystemHelper; import com.redhat.rhn.manager.MissingCapabilityException; import com.redhat.rhn.manager.configuration.ConfigurationManager; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; /** * ServerConfigChannelHandler * @version $Rev$ * @xmlrpc.namespace system.config * @xmlrpc.doc Provides methods to access and modify many aspects of * configuration channels and server association. * basically system.config name space */ public class ServerConfigHandler extends BaseHandler { /** * List files in a given server * @param loggedInUser The current user * @param sid the server id * @param listLocal true if a list of paths in local override is desired * false if list of paths in sandbox channel is desired * @return a list of dto's holding this info. * * @xmlrpc.doc Return the list of files in a given channel. * @xmlrpc.param #session_key() * @xmlrpc.param #param("int","serverId") * @xmlrpc.param #param("int","listLocal") * #options() * #item_desc ("1", "to return configuration files * in the system's local override configuration channel") * #item_desc ("0", "to return configuration files * in the system's sandbox configuration channel") * #options_end() * * @xmlrpc.returntype * #array() * $ConfigFileNameDtoSerializer * #array_end() */ public List<ConfigFileNameDto> listFiles(User loggedInUser, Integer sid, boolean listLocal) { XmlRpcSystemHelper sysHelper = XmlRpcSystemHelper.getInstance(); ConfigurationManager cm = ConfigurationManager.getInstance(); Server server = sysHelper.lookupServer(loggedInUser, sid); if (listLocal) { DataResult<ConfigFileNameDto> dtos = cm.listFileNamesForSystemQuick(loggedInUser, server, null); return dtos; } List<ConfigFileNameDto> files = new LinkedList<ConfigFileNameDto>(); List <ConfigFileDto> currentFiles = cm.listCurrentFiles(loggedInUser, server.getSandboxOverride(), null); for (ConfigFileDto dto : currentFiles) { files.add(ConfigFileNameDtoSerializer.toNameDto(dto, ConfigChannelType.SANDBOX, null)); } return files; } /** * Creates a NEW path(file/directory) with the given path or updates an existing path * with the given contents in a given server. * @param loggedInUser The current user * @param sid the server id. * @param path the path of the given text file. * @param isDir true if this is a directory path, false if its to be a file path * @param data a map containing properties pertaining to the given path.. * for directory paths - 'data' will hold values for -> * owner, group, permissions * for file paths - 'data' will hold values for-> * contents, owner, group, permissions, macro-start-delimiter, macro-end-delimiter * @param commitToLocal true if we want to commit the file to * the server's local channel false if we want to commit it to sandbox. * @return returns the new created or updated config revision.. * @since 10.2 * * @xmlrpc.doc Create a new file (text or binary) or directory with the given path, or * update an existing path on a server. * @xmlrpc.param #session_key() * @xmlrpc.param #param("int","serverId") * @xmlrpc.param #param_desc("string","path", * "the configuration file/directory path") * @xmlrpc.param #param( "boolean", "isDir") * #options() * #item_desc ("True", "if the path is a directory") * #item_desc ("False", "if the path is a file") * #options_end() * @xmlrpc.param * #struct("path info") * #prop_desc("string","contents", * "Contents of the file (text or base64 encoded if binary) * ((only for non-directories)") * #prop_desc("boolean","contents_enc64", "Identifies base64 encoded content * (default: disabled, only for non-directories).") * #prop_desc("string","owner", "Owner of the file/directory.") * #prop_desc("string","group", "Group name of the file/directory.") * #prop_desc("string","permissions", * "Octal file/directory permissions (eg: 644)") * #prop_desc("string","macro-start-delimiter", * "Config file macro end delimiter. Use null or empty string * to accept the default. (only for non-directories)") * #prop_desc("string","macro-end-delimiter", * "Config file macro end delimiter. Use null or empty string * to accept the default. (only for non-directories)") * #prop_desc("string","selinux_ctx", * "SeLinux context (optional)") * #prop_desc("int", "revision", "next revision number, auto increment for null") * #prop_desc("boolean", "binary", "mark the binary content, if True, * base64 encoded content is expected (only for non-directories)") * #struct_end() * @xmlrpc.param #param("int","commitToLocal") * #options() * #item_desc ("1", "to commit configuration files * to the system's local override configuration channel") * #item_desc ("0", "to commit configuration files * to the system's sandbox configuration channel") * #options_end() * @xmlrpc.returntype * $ConfigRevisionSerializer */ public ConfigRevision createOrUpdatePath(User loggedInUser, Integer sid, String path, boolean isDir, Map<String, Object> data, boolean commitToLocal) { // confirm that the user only provided valid keys in the map Set<String> validKeys = new HashSet<String>(); validKeys.add(ConfigRevisionSerializer.OWNER); validKeys.add(ConfigRevisionSerializer.GROUP); validKeys.add(ConfigRevisionSerializer.PERMISSIONS); validKeys.add(ConfigRevisionSerializer.REVISION); validKeys.add(ConfigRevisionSerializer.SELINUX_CTX); if (!isDir) { validKeys.add(ConfigRevisionSerializer.CONTENTS); validKeys.add(ConfigRevisionSerializer.CONTENTS_ENC64); validKeys.add(ConfigRevisionSerializer.MACRO_START); validKeys.add(ConfigRevisionSerializer.MACRO_END); validKeys.add(ConfigRevisionSerializer.BINARY); } validateMap(validKeys, data); XmlRpcSystemHelper sysHelper = XmlRpcSystemHelper.getInstance(); Server server = sysHelper.lookupServer(loggedInUser, sid); ConfigChannel channel; if (commitToLocal) { channel = server.getLocalOverride(); } else { channel = server.getSandboxOverride(); } XmlRpcConfigChannelHelper configHelper = XmlRpcConfigChannelHelper.getInstance(); return configHelper.createOrUpdatePath(loggedInUser, channel, path, isDir ? ConfigFileType.dir() : ConfigFileType.file(), data); } /** * Creates a NEW symbolic link with the given path or updates an existing path * with the given target_path in a given server. * @param loggedInUser The current user * @param sid the server id. * @param path the path of the given text file. * @param data a map containing properties pertaining to the given path.. * 'data' will hold values for -> * target_paths, selinux_ctx * @param commitToLocal true if we want to commit the file to * the server's local channel false if we want to commit it to sandbox. * @return returns the new created or updated config revision.. * @since 10.2 * * @xmlrpc.doc Create a new symbolic link with the given path, or * update an existing path. * @xmlrpc.param #session_key() * @xmlrpc.param #param("int","serverId") * @xmlrpc.param #param_desc("string","path", * "the configuration file/directory path") * @xmlrpc.param * #struct("path info") * #prop_desc("string","target_path", * "The target path for the symbolic link") * #prop_desc("string", "selinux_ctx", "SELinux Security context (optional)") * #prop_desc("int", "revision", "next revision number, auto increment for null") * #struct_end() * @xmlrpc.param #param("int","commitToLocal") * #options() * #item_desc ("1", "to commit configuration files * to the system's local override configuration channel") * #item_desc ("0", "to commit configuration files * to the system's sandbox configuration channel") * #options_end() * @xmlrpc.returntype * $ConfigRevisionSerializer */ public ConfigRevision createOrUpdateSymlink(User loggedInUser, Integer sid, String path, Map<String, Object> data, boolean commitToLocal) { // confirm that the user only provided valid keys in the map Set<String> validKeys = new HashSet<String>(); validKeys.add(ConfigRevisionSerializer.TARGET_PATH); validKeys.add(ConfigRevisionSerializer.SELINUX_CTX); validKeys.add(ConfigRevisionSerializer.REVISION); validateMap(validKeys, data); XmlRpcSystemHelper sysHelper = XmlRpcSystemHelper.getInstance(); Server server = sysHelper.lookupServer(loggedInUser, sid); ConfigChannel channel; if (commitToLocal) { channel = server.getLocalOverride(); } else { channel = server.getSandboxOverride(); } XmlRpcConfigChannelHelper configHelper = XmlRpcConfigChannelHelper.getInstance(); return configHelper.createOrUpdatePath(loggedInUser, channel, path, ConfigFileType.symlink(), data); } /** * Given a list of paths and a server the method returns details about the latest * revisions of the paths. * @param loggedInUser The current user * @param sid the server id * @param paths a list of paths to examine. * @param searchLocal true look at local overrides, false * to look at sandbox overrides * @return a list containing the latest config revisions of the requested paths. * @since 10.2 * * @xmlrpc.doc Given a list of paths and a server, returns details about * the latest revisions of the paths. * @xmlrpc.param #session_key() * @xmlrpc.param #param("int","serverId") * @xmlrpc.param #array_single("string","paths to lookup on.") * @xmlrpc.param #param("int","searchLocal") * #options() * #item_desc ("1", "to search configuration file paths * in the system's local override configuration or * systems subscribed central channels") * #item_desc ("0", "to search configuration file paths * in the system's sandbox configuration channel") * #options_end() * @xmlrpc.returntype * #array() * $ConfigRevisionSerializer * #array_end() */ public List<ConfigRevision> lookupFileInfo(User loggedInUser, Integer sid, List<String> paths, boolean searchLocal) { XmlRpcSystemHelper sysHelper = XmlRpcSystemHelper.getInstance(); Server server = sysHelper.lookupServer(loggedInUser, sid); ConfigurationManager cm = ConfigurationManager.getInstance(); List <ConfigRevision> revisions = new LinkedList<ConfigRevision>(); for (String path : paths) { ConfigFile cf; if (searchLocal) { cf = cm.lookupConfigFile(loggedInUser, server.getLocalOverride().getId(), path); if (cf == null) { for (ConfigChannel cn : server.getConfigChannels()) { cf = cm.lookupConfigFile(loggedInUser, cn.getId(), path); if (cf != null) { revisions.add(cf.getLatestConfigRevision()); break; } } } } else { cf = cm.lookupConfigFile(loggedInUser, server.getSandboxOverride().getId(), path); } if (cf != null) { revisions.add(cf.getLatestConfigRevision()); } } return revisions; } /** * Removes a list of paths from a local or sandbox channel of a server.. * @param loggedInUser The current user * @param sid the server id to remove the files from.. * @param paths the list of paths to delete. * @param deleteFromLocal true if we want to delete form local channel * false if we want to delete from sandbox.. * @return 1 if successful with the operation errors out otherwise. * * * @xmlrpc.doc Removes file paths from a local or sandbox channel of a server. * @xmlrpc.param #session_key() * @xmlrpc.param #param("int","serverId") * @xmlrpc.param #array_single("string","paths to remove.") * @xmlrpc.param #param("boolean","deleteFromLocal") * #options() * #item_desc ("True", "to delete configuration file paths * from the system's local override configuration channel") * #item_desc ("False", "to delete configuration file paths * from the system's sandbox configuration channel") * #options_end() * @xmlrpc.returntype #return_int_success() * */ public int deleteFiles(User loggedInUser, Integer sid, List <String> paths, boolean deleteFromLocal) { XmlRpcSystemHelper sysHelper = XmlRpcSystemHelper.getInstance(); ConfigurationManager cm = ConfigurationManager.getInstance(); Server server = sysHelper.lookupServer(loggedInUser, sid); List<ConfigFile> cfList = new ArrayList<ConfigFile>(); for (String path : paths) { ConfigFile cf; if (deleteFromLocal) { cf = cm.lookupConfigFile(loggedInUser, server.getLocalOverride().getId(), path); if (cf == null) { throw new NoSuchConfigFilePathException(path); } } else { cf = cm.lookupConfigFile(loggedInUser, server.getSandboxOverride().getId(), path); } cfList.add(cf); } for (ConfigFile cf : cfList) { cm.deleteConfigFile(loggedInUser, cf); } return 1; } /** * Schedules a deploy action for all the configuration files * of a given list of servers. * * @param loggedInUser The current user * @param serverIds list of IDs of the server to schedule the deploy action * @param date date of the deploy action.. * @return 1 on success, raises exceptions otherwise. * * @xmlrpc.doc Schedules a deploy action for all the configuration files * on the given list of systems. * @xmlrpc.param #session_key() * @xmlrpc.param #array_single("int", * "id of the systems to schedule configuration files deployment") * @xmlrpc.param #param_desc($date, "date", * "Earliest date for the deploy action.") * @xmlrpc.returntype #return_int_success() */ public int deployAll(User loggedInUser, List<Number> serverIds, Date date) { XmlRpcSystemHelper helper = XmlRpcSystemHelper.getInstance(); List <Server> servers = new ArrayList<Server>(serverIds.size()); for (Number sid : serverIds) { servers.add(helper.lookupServer(loggedInUser, sid)); } ConfigurationManager manager = ConfigurationManager.getInstance(); try { manager.deployConfiguration(loggedInUser, servers, date); } catch (MissingCapabilityException e) { throw new com.redhat.rhn.frontend.xmlrpc.MissingCapabilityException( e.getCapability(), e.getServer()); } return 1; } /** * List all the global channels associated to a system * in the order of their ranking. * @param loggedInUser The current user * @param sid a system id * @return a list of global config channels associated to the given * system in the order of their ranking.. * * @xmlrpc.doc List all global configuration channels associated to a * system in the order of their ranking. * @xmlrpc.param #session_key() * @xmlrpc.param #param("int","serverId") * @xmlrpc.returntype * #array() * $ConfigChannelSerializer * #array_end() */ public List<ConfigChannel> listChannels(User loggedInUser, Integer sid) { XmlRpcSystemHelper helper = XmlRpcSystemHelper.getInstance(); Server server = helper.lookupServer(loggedInUser, sid); return server.getConfigChannels(); } /** * Given a list of servers and configuration channels, * this method inserts the configuration channels to either the top or * the bottom (whichever you specify) of a system's subscribed * configuration channels list. The ordering of the configuration channels * provided in the add list is maintained while adding. * If one of the configuration channels in the 'add' list * has been previously subscribed by a server, the * subscribed channel will be re-ranked to the appropriate place. * @param loggedInUser The current user * @param serverIds a list of ids of servers to add the configuration channels to. * @param configChannelLabels set of configuration channels labels * @param addToTop if true inserts the configuration channels list to * the top of the configuration channels list of a server * @return 1 on success 0 on failure * * @xmlrpc.doc Given a list of servers and configuration channels, * this method appends the configuration channels to either the top or * the bottom (whichever you specify) of a system's subscribed * configuration channels list. The ordering of the configuration channels * provided in the add list is maintained while adding. * If one of the configuration channels in the 'add' list * has been previously subscribed by a server, the * subscribed channel will be re-ranked to the appropriate place. * @xmlrpc.param #session_key() * @xmlrpc.param #array_single("int", * "IDs of the systems to add the channels to.") * @xmlrpc.param #array_single("string", * "List of configuration channel labels in the ranked order.") * @xmlrpc.param #param("boolean","addToTop") * #options() * #item_desc ("true", "to prepend the given channels * list to the top of the configuration channels list of a server") * #item_desc ("false", "to append the given channels * list to the bottom of the configuration channels list of a server") * #options_end() * * @xmlrpc.returntype #return_int_success() */ public int addChannels(User loggedInUser, List<Number> serverIds, List<String> configChannelLabels, boolean addToTop) { XmlRpcSystemHelper helper = XmlRpcSystemHelper.getInstance(); List <Server> servers = helper.lookupServers(loggedInUser, serverIds); XmlRpcConfigChannelHelper configHelper = XmlRpcConfigChannelHelper.getInstance(); List <ConfigChannel> channels = configHelper. lookupGlobals(loggedInUser, configChannelLabels); ConfigChannelListProcessor proc = new ConfigChannelListProcessor(); if (addToTop) { Collections.reverse(channels); } for (Server server : servers) { for (ConfigChannel chan : channels) { if (addToTop) { proc.add(server.getConfigChannels(), chan, 0); } else { proc.add(server.getConfigChannels(), chan); } } } return 1; } /** * replaces the existing set of config channels for a given * list of servers. * Note: it ranks these channels according to the array order of * configChannelLabels method parameter * @param loggedInUser The current user * @param serverIds a list of ids of servers to change the config files for.. * @param configChannelLabels sets channels labels * @return 1 on success 0 on failure * * @xmlrpc.doc Replace the existing set of config channels on the given servers. * Channels are ranked according to their order in the configChannelLabels * array. * @xmlrpc.param #session_key() * @xmlrpc.param #array_single("int", * "IDs of the systems to set the channels on.") * @xmlrpc.param #array_single("string", * "List of configuration channel labels in the ranked order.") * * @xmlrpc.returntype #return_int_success() */ public int setChannels(User loggedInUser, List<Number> serverIds, List<String> configChannelLabels) { XmlRpcSystemHelper helper = XmlRpcSystemHelper.getInstance(); List <Server> servers = helper.lookupServers(loggedInUser, serverIds); XmlRpcConfigChannelHelper configHelper = XmlRpcConfigChannelHelper.getInstance(); List <ConfigChannel> channels = configHelper. lookupGlobals(loggedInUser, configChannelLabels); ConfigChannelListProcessor proc = new ConfigChannelListProcessor(); for (Server server : servers) { proc.replace(server.getConfigChannels(), channels); } return 1; } /** * removes selected channels from list of config channels provided * for a given list of servers. * @param loggedInUser The current user * @param serverIds the list of server ids. * @param configChannelLabels sets channels labels * @return 1 on success 0 on failure * * @xmlrpc.doc Remove config channels from the given servers. * @xmlrpc.param #session_key() * @xmlrpc.param #array_single("int", "the IDs of the systems from which you * would like to remove configuration channels..") * @xmlrpc.param #array_single("string", * "List of configuration channel labels to remove.") * @xmlrpc.returntype #return_int_success() */ public int removeChannels(User loggedInUser, List<Number> serverIds, List<String> configChannelLabels) { XmlRpcSystemHelper helper = XmlRpcSystemHelper.getInstance(); List<Server> servers = helper.lookupServers(loggedInUser, serverIds); XmlRpcConfigChannelHelper configHelper = XmlRpcConfigChannelHelper.getInstance(); List <ConfigChannel> channels = configHelper. lookupGlobals(loggedInUser, configChannelLabels); ConfigChannelListProcessor proc = new ConfigChannelListProcessor(); boolean success = true; for (Server server : servers) { success = success && proc.remove(server.getConfigChannels(), channels); } if (success) { return 1; } return 0; } }