/*
* RHQ Management Platform
* Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.configuration;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import org.jetbrains.annotations.Nullable;
import org.quartz.SchedulerException;
import org.rhq.core.clientapi.server.configuration.ConfigurationUpdateResponse;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.configuration.AbstractResourceConfigurationUpdate;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.PluginConfigurationUpdate;
import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
import org.rhq.core.domain.configuration.composite.ConfigurationUpdateComposite;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
import org.rhq.core.domain.configuration.group.AbstractGroupConfigurationUpdate;
import org.rhq.core.domain.configuration.group.GroupPluginConfigurationUpdate;
import org.rhq.core.domain.configuration.group.GroupResourceConfigurationUpdate;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.configuration.job.GroupPluginConfigurationUpdateJob;
import org.rhq.enterprise.server.resource.ResourceNotFoundException;
/**
* The configuration manager which allows you to request resource configuration changes, view current resource
* configuration and previous update history and view/edit plugin configuration.
*
* @author John Mazzitelli
* @author Ian Springer
*/
@Local
public interface ConfigurationManagerLocal extends ConfigurationManagerRemote {
/**
* Updates the plugin configuration used to connect and communicate with the resource using the information in the
* passed {@link PluginConfigurationUpdate} object. This update object will be changed to reflect the result of the
* plugin configuration update attempt. This is an internal method called by
* {@link #updatePluginConfiguration(Subject, int, Configuration)} and {@link GroupPluginConfigurationUpdateJob}
* . It is not intended to be used for general, public consumption.
*
* @param update a previously server-side persisted update, which has not yet made it to the agent
*/
void completePluginConfigurationUpdate(PluginConfigurationUpdate update);
void completePluginConfigurationUpdate(Integer updateId);
/** This does not perform permission checks and should be used internally only. In general, use
* {@link #getPluginConfiguration(Subject, int)}.
*/
Configuration getPluginConfiguration(int resourceId);
/** This does not perform permission checks and should be used internally only. In general, use
* {@link #getCurrentResourceConfiguration}.
* @throws FetchException TODO
*/
Configuration getResourceConfiguration(int resourceId);
Configuration getLiveResourceConfiguration(Subject subject, int resourceId, boolean pingAgentFirst,
boolean fromStructured) throws Exception;
PageList<PluginConfigurationUpdate> findPluginConfigurationUpdates(Subject subject, int resourceId, Long beginDate,
Long endDate, PageControl pc);
/**
* Returns the list of all Resource configuration updates for the given Resource, in reverse of the order in which
* they were created (i.e. most recent update will be the first item in the list). This will show you an audit trail
* of the update history for the Resource (who updated it, when and what did they change). You can pick one
* configuration version to later rollback to that version via
* {@link #updateResourceConfiguration(Subject, int, Configuration)}.
*
* @param subject the user who wants to see the information
* @param resourceId the resource whose update requests are to be returned, if null will not filter by resourceId
* @param beginDate filter used to show only results occurring after this epoch millis parameter, nullable
* @param endDate filter used to show only results occurring before this epoch millis parameter, nullable
* @param suppressOldest if true, will not include the oldest element in the history (usually the initial update)
* @param pc the pagination controls
*
* @return the Resource's complete list of updates (will be empty (not <code>null</code>) if none)
*/
PageList<ResourceConfigurationUpdate> findResourceConfigurationUpdates(Subject subject, Integer resourceId,
Long beginDate, Long endDate, boolean suppressOldest, PageControl pc);
/**
* Returns a single plugin configuration update.
*
* @param subject the user who wants to see the information
* @param configurationUpdateId the ID of the configuration update entity to return
*
* @return the plugin configuration update
*/
PluginConfigurationUpdate getPluginConfigurationUpdate(Subject subject, int configurationUpdateId);
/**
* Returns a single resource configuration update
*
* @param subject the user who wants to see the information
* @param configurationUpdateId the ID of the configuration update entity to return
*
* @return the resource configuration update
*/
ResourceConfigurationUpdate getResourceConfigurationUpdate(Subject subject, int configurationUpdateId);
/**
* For internal use only - do not call this method. This is for
* {@link #updateResourceConfiguration(Subject, int, Configuration)} to call with REQUIRES_NEW transaction scope so
* it can force the new request to be committed to the DB. Also used by
* {@link #getLatestResourceConfigurationUpdate(Subject, int)} and
* {@link #scheduleGroupResourceConfigurationUpdate}.
*
* @param subject ASSUMES CONFIGURE_WRITE perm for resource in question, no authz checks in this method.
* @param resourceId
* @param newConfiguration
* @param newStatus
* @param newSubject user to associate with this update change (may be <code>null</code>)
*
* @param isPartofGroupUpdate
* @return the persisted Resource Configuration update, or null if the specified Configuration is identical to the
* currently persisted Configuration. Note, on success the normally lazy-loaded
* ResourceConfigurationUpdate.resource.agent will be provided.
*/
@Nullable
ResourceConfigurationUpdate persistResourceConfigurationUpdateInNewTransaction(Subject subject, int resourceId,
Configuration newConfiguration, ConfigurationUpdateStatus newStatus, String newSubject,
boolean isPartofGroupUpdate) throws ResourceNotFoundException, ConfigurationUpdateStillInProgressException;
/**
* A callback method that is called when an agent has completed updating a resource's configuration.
*
* @param response information that contains the status of the update (i.e. was it successfully updated or did it
* fail?) as well as the configuration if it failed (with the properties containing error messages
* to describe what failed). If the update was a success, the completed request's configuration will
* be <code>null</code> to indicate that the configuration that was sent to the agent was used
* as-is.
*/
void completeResourceConfigurationUpdate(ConfigurationUpdateResponse response);
void checkForCompletedGroupResourceConfigurationUpdate(int resourceConfigUpdateId);
ConfigurationUpdateResponse executePluginConfigurationUpdate(PluginConfigurationUpdate update);
/**
* This deletes the update information belonging to the {@link AbstractResourceConfigurationUpdate} object with the
* given ID. Once this returns, the complete audit trail for that update will be gone and you will not be able to
* rollback to that configuration.
*
* <p>Under normal circumstances, you will not want to purge an update that is currently in progress. However, there
* may be conditions in which an update request "gets stuck" in the in-progress state, even though you know the
* agent will never report the completed request (typically caused by an unusual crash of the agent). In this case,
* you should pass <code>true</code> in for the <code>purgeInProgress</code> parameter to tell this method to delete
* the request even if it says it is in-progress.
*
* @param subject the user who is requesting the purge
* @param configurationUpdateId identifies the update record to be deleted
* @param purgeInProgress if <code>true</code>, delete it even if its
* {@link ConfigurationUpdateStatus#INPROGRESS in progress}
*/
public void purgePluginConfigurationUpdate(Subject subject, int configurationUpdateId, boolean purgeInProgress);
/**
* This deletes the update information belonging to the {@link AbstractResourceConfigurationUpdate} object with the
* given ID. Once this returns, the complete audit trail for that update will be gone and you will not be able to
* rollback to that configuration.
*
* <p>Under normal circumstances, you will not want to purge an update that is currently in progress. However, there
* may be conditions in which an update request "gets stuck" in the in-progress state, even though you know the
* agent will never report the completed request (typically caused by an unusual crash of the agent). In this case,
* you should pass <code>true</code> in for the <code>purgeInProgress</code> parameter to tell this method to delete
* the request even if it says it is in-progress.
*
* @param subject the user who is requesting the purge
* @param configurationUpdateId identifies the update record to be deleted
* @param purgeInProgress if <code>true</code>, delete it even if its
* {@link ConfigurationUpdateStatus#INPROGRESS in progress}
*/
void purgeResourceConfigurationUpdate(Subject subject, int configurationUpdateId, boolean purgeInProgress);
/**
* Merge the specified configuration update into the DB.
*
* @param configurationUpdate a configuration update
*
* @return an attached copy of the configuration update
*/
AbstractResourceConfigurationUpdate mergeConfigurationUpdate(AbstractResourceConfigurationUpdate configurationUpdate);
/**
* This is a generic method that any caller can use to obtain any configuration given a configuration ID. This can
* be used to obtain any configuration, which includes such things as an operation's parameters or an operations
* results.
*
* @param id identifies the configuration to return
*
* @return the configuration with the given ID, or <code>null</code> if there is no configuration with that ID
*/
Configuration getConfigurationById(int id);
/**
* This is a convenience method that is equivalent to the following: <code>
* definition.getDefaultTemplate().getConfiguration()</code> If the definition is already a managed bean, then there
* is no real reason to call this since EJB3 will traverse the object relationships just fine. However, if the
* definition is detached from the managed context, and because of the lazy-loading semantics of the entities
* involved in the call chain above, then you can use this method since it will re-attach it and get the
* configuration from the default template as shown above.
*
* @param definition a configuration definition
*
* @return the {@link Configuration} from the default {@link ConfigurationTemplate} of the passed definition
*/
Configuration getConfigurationFromDefaultTemplate(ConfigurationDefinition definition);
GroupPluginConfigurationUpdate getGroupPluginConfigurationById(int configurationUpdateId);
PageList<ConfigurationUpdateComposite> findPluginConfigurationUpdateCompositesByParentId(int configurationUpdateId,
PageControl pageControl);
PageList<ConfigurationUpdateComposite> findResourceConfigurationUpdateCompositesByParentId(Subject subject,
int configurationUpdateId, PageControl pageControl);
PageList<Integer> findPluginConfigurationUpdatesByParentId(int configurationUpdateId, PageControl pageControl);
long getPluginConfigurationUpdateCountByParentId(int configurationUpdateId);
int createGroupConfigurationUpdate(AbstractGroupConfigurationUpdate update) throws SchedulerException;
PageList<GroupPluginConfigurationUpdate> findGroupPluginConfigurationUpdates(int groupId, PageControl pc);
PageList<GroupResourceConfigurationUpdate> findGroupResourceConfigurationUpdates(Subject subject, int groupId,
PageControl pc);
ConfigurationUpdateStatus updateGroupResourceConfigurationUpdateStatus(int groupResourceConfigurationUpdateId,
String errorMessages);
ConfigurationUpdateStatus updateGroupPluginConfigurationUpdateStatus(int groupPluginConfigurationUpdateId,
String errorMessages);
int deleteGroupPluginConfigurationUpdates(Subject subject, Integer resourceGroupId,
Integer[] groupPluginConfigurationUpdateIds);
int deleteGroupResourceConfigurationUpdates(Subject subject, Integer resourceGroupId,
Integer[] groupResourceConfigurationUpdateIds);
void updateGroupConfigurationUpdate(AbstractGroupConfigurationUpdate groupUpdate);
void deleteConfigurations(List<Integer> configurationIds);
void deleteProperties(int[] propertyIds);
PageList<Integer> findResourceConfigurationUpdatesByParentId(int groupConfigurationUpdateId, PageControl pageControl);
long getResourceConfigurationUpdateCountByParentId(int groupConfigurationUpdateId);
void executeResourceConfigurationUpdate(int updateId);
GroupResourceConfigurationUpdate getGroupResourceConfigurationById(int configurationUpdateId);
Map<Integer, Configuration> getResourceConfigurationMapForGroupUpdate(Subject subject,
Integer groupResourceConfigurationUpdateId);
/**
* Returns the current Resource configurations for the members in the specified compatible group.
*
* @param subject the current subject
* @param groupId the id of the compatible group
* @return
* @throws ConfigurationUpdateInProgressException if config updates, for the group or any member, are in progress,
* @throws Exception if 1) one or more of the group's members are DOWN, or 2) we fail to retrieve one or more member
* live configs from the corresponding Agents
*/
Map<Integer, Configuration> getResourceConfigurationsForCompatibleGroup(Subject subject, int groupId)
throws ConfigurationUpdateStillInProgressException, Exception;
Map<Integer, Configuration> getPluginConfigurationsForCompatibleGroup(Subject subject, int groupId)
throws ConfigurationUpdateStillInProgressException, Exception;
Map<Integer, Configuration> getPluginConfigurationMapForGroupUpdate(Subject subject,
Integer groupPluginConfigurationUpdateId);
/**
* The purpose of this method is really to clean up requests when we detect
* they probably will never move out of the in-progress status. This will occur if the
* Agent dies before it has a chance to report success/failure. In that case, we'll never
* get an Agent completion message and the update request will remain in progress status forever.
* This method just tries to detect this scenario - if it finds an update request that has been
* in progress for a very long time, we assume we'll never hear from the Agent and time out
* that request (that is, set its status to FAILURE and set an error string that says the request
* timed out).
*/
void checkForTimedOutConfigurationUpdateRequests();
public Configuration getConfiguration(Subject subject, int configurationId);
ResourceConfigurationUpdate getLatestResourceConfigurationUpdate(Subject subject, int resourceId,
boolean fromStructured);
boolean isGroupPluginConfigurationUpdateInProgress(Subject subject, int groupId);
boolean isPluginConfigurationUpdateInProgress(Subject subject, int resourceId);
ResourceConfigurationUpdate updateStructuredOrRawConfiguration(Subject subject, int resourceId,
Configuration newConfiguration, boolean fromStructured) throws ResourceNotFoundException,
ConfigurationUpdateStillInProgressException;
/**
* This method is called when the plugin container reports a new Resource configuration after an external change was
* detected.
*
* @param resourceId the Resource's id
* @param configuration the updated configuration
*/
void setResourceConfiguration(int resourceId, Configuration configuration);
Configuration mergeConfiguration(Configuration config);
ConfigurationDefinition getOptionsForConfigurationDefinition(Subject subject, int resourceId,
int parentResourceId, ConfigurationDefinition def);
/**
* Dedicated method for supporting resource upgrade of plugin configuration. Similar to
* {@link #updatePluginConfiguration(Subject, int, Configuration)} but does not inform the agent for
* two reasons: first, the agent is already updated (it initiates the update and two, callingback into
* the agent would lock the plugin container, as this is during PC initialization. Also, it does not
* validate the newConfiguration because the agent is allowed to update read-only properties during an
* upgrade.
*
* @param subject The logged in user's subject.
* @param resourceId a {@link Resource} id
* @param newConfiguration the new plugin configuration
*
* @return the plugin configuration update item corresponding to this request
*/
PluginConfigurationUpdate upgradePluginConfiguration(Subject subject, int resourceId, Configuration newConfiguration)
throws ResourceNotFoundException;
}