From caf869ff17ba3db281f566c630bc7a629e7cc3ff Mon Sep 17 00:00:00 2001 From: John Mazzitelli Date: Thu, 3 Dec 2009 15:07:22 -0500 Subject: this is a patch that is a proof-of-concept to get RHQ to support configuration remediation --- rhq-config-remediation-patch.txt | 552 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 552 insertions(+) create mode 100644 rhq-config-remediation-patch.txt diff --git a/rhq-config-remediation-patch.txt b/rhq-config-remediation-patch.txt new file mode 100644 index 0000000..dbb5935 --- /dev/null +++ b/rhq-config-remediation-patch.txt @@ -0,0 +1,552 @@ +From 6aeb74f8938a2f8d390cbe8062b7a55a70cdd5a6 Mon Sep 17 00:00:00 2001 +From: John Mazzitelli +Date: Tue, 1 Dec 2009 13:17:12 -0500 +Subject: [PATCH 1/3] first attempt at config freeze + +--- + .../src/main/scripts/dbsetup/inventory-schema.xml | 1 + + .../core/domain/configuration/Configuration.java | 16 +++--- + .../org/rhq/core/domain/resource/Resource.java | 15 ++++++ + .../history/ListConfigurationUpdateUIBean.java | 50 ++++++++++++++++++++ + .../rhq/resource/configuration/history.xhtml | 14 ++++- + .../configuration/ConfigurationManagerBean.java | 48 ++++++++++++++++++- + .../configuration/ConfigurationManagerLocal.java | 22 +++++++-- + .../ConfigurationServerServiceImpl.java | 24 ++++++++- + 8 files changed, 168 insertions(+), 22 deletions(-) + +diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/inventory-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/inventory-schema.xml +index 2f25ff1..6c4eba6 100644 +--- a/modules/core/dbutils/src/main/scripts/dbsetup/inventory-schema.xml ++++ b/modules/core/dbutils/src/main/scripts/dbsetup/inventory-schema.xml +@@ -93,6 +93,7 @@ + + + ++ + + + +diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java +index 62bd8ce..530ec65 100644 +--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java ++++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java +@@ -32,10 +32,10 @@ import java.io.ObjectOutput; + import java.io.ObjectOutputStream; + import java.util.Collection; + import java.util.HashMap; ++import java.util.HashSet; + import java.util.LinkedHashMap; + import java.util.Map; + import java.util.Set; +-import java.util.HashSet; + + import javax.persistence.Column; + import javax.persistence.Entity; +@@ -104,6 +104,8 @@ import org.rhq.core.domain.util.serial.HibernateUtil; + + "select r.pluginConfiguration from Resource r where r.id = :resourceId"), + @NamedQuery(name = Configuration.QUERY_GET_RESOURCE_CONFIG_BY_RESOURCE_ID, query = "" // + + "select r.resourceConfiguration from Resource r where r.id = :resourceId"), ++ @NamedQuery(name = Configuration.QUERY_GET_FROZEN_RESOURCE_CONFIG_BY_RESOURCE_ID, query = "" // ++ + "select r.frozenResourceConfiguration from Resource r where r.id = :resourceId"), + @NamedQuery(name = Configuration.QUERY_GET_RESOURCE_CONFIG_MAP_BY_GROUP_ID, query = "" // + + "SELECT r.id, r.resourceConfiguration " // + + " FROM ResourceGroup rg " // +@@ -137,6 +139,7 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert + + public static final String QUERY_GET_PLUGIN_CONFIG_BY_RESOURCE_ID = "Configuration.getPluginConfigByResourceId"; + public static final String QUERY_GET_RESOURCE_CONFIG_BY_RESOURCE_ID = "Configuration.getResourceConfigByResourceId"; ++ public static final String QUERY_GET_FROZEN_RESOURCE_CONFIG_BY_RESOURCE_ID = "Configuration.getFrozenResourceConfigByResourceId"; + public static final String QUERY_GET_RESOURCE_CONFIG_MAP_BY_GROUP_ID = "Configuration.getResourceConfigMapByGroupId"; + public static final String QUERY_GET_PLUGIN_CONFIG_MAP_BY_GROUP_ID = "Configuration.getPluginConfigMapByGroupId"; + public static final String QUERY_GET_RESOURCE_CONFIG_MAP_BY_GROUP_UPDATE_ID = "Configuration.getResourceConfigMapByGroupUpdateId"; +@@ -157,7 +160,7 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert + private Map properties = new LinkedHashMap(); + + @OneToMany(mappedBy = "configuration", fetch = FetchType.EAGER) +- @Cascade({CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DELETE_ORPHAN}) ++ @Cascade( { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DELETE_ORPHAN }) + private Set rawConfigurations = new HashSet(); + + @Column(name = "NOTES") +@@ -581,11 +584,7 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert + builder.append("], rawConfigurations["); + + for (RawConfiguration rawConfig : rawConfigurations) { +- builder.append("[") +- .append(rawConfig.getPath()) +- .append(", ") +- .append(rawConfig.getSha256()) +- .append("]"); ++ builder.append("[").append(rawConfig.getPath()).append(", ").append(rawConfig.getSha256()).append("]"); + } + builder.append("]"); + } +@@ -650,7 +649,8 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert + out.writeLong(ctime); + out.writeLong(mtime); + } +- // Explicitly do not send the history relationship ++ ++ // Explicitly do not send the history relationship + private Map createDeepCopyOfMap() { + Map copy = new HashMap(); + for (Map.Entry entry : this.properties.entrySet()) { +diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java +index 0c4b284..f9fa6cc 100644 +--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java ++++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java +@@ -89,6 +89,15 @@ import org.rhq.core.domain.util.serial.ExternalizableStrategy; + */ + @Entity + @NamedQueries( { ++ ++ @NamedQuery(name = Resource.UPDATE_SET_FROZEN_RES_CONFIG, query = "" // ++ + "UPDATE Resource r " ++ + " SET r.frozenResourceConfiguration = (SELECT ch.configuration FROM ResourceConfigurationUpdate ch WHERE ch.id = :configUpdateId)" ++ + " WHERE r.id=:id"), ++ @NamedQuery(name = Resource.UPDATE_UNSET_FROZEN_RES_CONFIG, query = "" // ++ + "UPDATE Resource r " // ++ + " SET r.frozenResourceConfiguration = NULL" // ++ + " WHERE r.id=:id"), + @NamedQuery(name = Resource.QUERY_FIND_PROBLEM_RESOURCES_ALERT_ADMIN, query = "" // + + " SELECT DISTINCT new org.rhq.core.domain.resource.composite.ProblemResourceComposite" + + " ( " +@@ -852,6 +861,8 @@ public class Resource implements Comparable, Externalizable { + + public static final String QUERY_RESOURCE_REPORT = "Resource.findResourceReport"; + public static final String QUERY_RESOURCE_VERSION_REPORT = "Resource.findResourceVersionReport"; ++ public static final String UPDATE_SET_FROZEN_RES_CONFIG = "Resource.updateSetFrozenResourceConfig"; ++ public static final String UPDATE_UNSET_FROZEN_RES_CONFIG = "Resource.updateUnsetFrozenResourceConfig"; + + private static final long serialVersionUID = 1L; + +@@ -922,6 +933,10 @@ public class Resource implements Comparable, Externalizable { + @XmlTransient + private Resource parentResource; + ++ @JoinColumn(name = "FROZEN_RES_CONFIG_ID", referencedColumnName = "ID") ++ @OneToOne(cascade = {}, fetch = FetchType.LAZY) ++ private Configuration frozenResourceConfiguration = null; ++ + @JoinColumn(name = "RES_CONFIGURATION_ID", referencedColumnName = "ID") + @OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY) + private Configuration resourceConfiguration = new Configuration(); +diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/history/ListConfigurationUpdateUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/history/ListConfigurationUpdateUIBean.java +index b3839fc..ab03167 100644 +--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/history/ListConfigurationUpdateUIBean.java ++++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/history/ListConfigurationUpdateUIBean.java +@@ -59,6 +59,56 @@ public class ListConfigurationUpdateUIBean extends PagedDataTableUIBean { + return dataModel; + } + ++ public String unfreeze() { ++ try { ++ Subject subject = EnterpriseFacesContextUtility.getSubject(); ++ Resource resource = EnterpriseFacesContextUtility.getResource(); ++ ConfigurationManagerLocal manager = LookupUtil.getConfigurationManager(); ++ ++ manager.unfreezeResourceConfiguration(subject, resource.getId()); ++ ++ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Unfroze resource configuration"); ++ } catch (Exception e) { ++ FacesContextUtility ++ .addMessage(FacesMessage.SEVERITY_ERROR, ++ "Failed to unfreeze resource configuration to version. Cause: " ++ + ThrowableUtil.getAllMessages(e, true)); ++ } ++ ++ return "success"; ++ } ++ ++ public String freeze() { ++ String rollbackTo = null; ++ ++ try { ++ rollbackTo = FacesContextUtility.getRequest().getParameter("selectedItems"); ++ ++ Subject subject = EnterpriseFacesContextUtility.getSubject(); ++ Resource resource = EnterpriseFacesContextUtility.getResource(); ++ ConfigurationManagerLocal manager = LookupUtil.getConfigurationManager(); ++ ++ manager.rollbackResourceConfiguration(subject, resource.getId(), Integer.parseInt(rollbackTo)); ++ ++ // We've just updated the current Configuration, so clear the current Configuration that is cached in the ++ // Session, so the config view/edit pages will not display a stale version of the Configuration. ++ ExistingResourceConfigurationUIBean configUIBean = FacesContextUtility ++ .getManagedBean(ExistingResourceConfigurationUIBean.class); ++ configUIBean.clearConfiguration(); ++ ++ manager.freezeResourceConfiguration(subject, resource.getId(), Integer.parseInt(rollbackTo)); ++ ++ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, ++ "Rolled back and froze resource configuration to version " + rollbackTo); ++ } catch (Exception e) { ++ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, ++ "Failed to rollback resource configuration to version " + rollbackTo + ". Cause: " ++ + ThrowableUtil.getAllMessages(e, true)); ++ } ++ ++ return "success"; ++ } ++ + public String rollback() { + String rollbackTo = null; + +diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/configuration/history.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/configuration/history.xhtml +index ac824f8..0b126bf 100644 +--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/configuration/history.xhtml ++++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/configuration/history.xhtml +@@ -186,14 +186,22 @@ + + + + + ++ ++ + +diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java +index 6a7d327..b61a522 100644 +--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java ++++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java +@@ -20,12 +20,12 @@ package org.rhq.enterprise.server.configuration; + + import java.util.ArrayList; + import java.util.Calendar; ++import java.util.Collection; ++import java.util.Collections; + import java.util.HashMap; + import java.util.List; + import java.util.Map; + import java.util.Set; +-import java.util.Collections; +-import java.util.Collection; + + import javax.ejb.EJB; + import javax.ejb.Stateless; +@@ -57,8 +57,8 @@ 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.Property; +-import org.rhq.core.domain.configuration.ResourceConfigurationUpdate; + import org.rhq.core.domain.configuration.RawConfiguration; ++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.group.AbstractGroupConfigurationUpdate; +@@ -135,6 +135,29 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf + @EJB + private SubjectManagerLocal subjectManager; + ++ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) ++ public void freezeResourceConfiguration(Subject subject, int resourceId, int configUpdateId) { ++ Query q = entityManager.createNamedQuery(Resource.UPDATE_SET_FROZEN_RES_CONFIG); ++ q.setParameter("id", resourceId); ++ q.setParameter("configUpdateId", configUpdateId); ++ int rows = q.executeUpdate(); ++ if (rows != 1) { ++ throw new RuntimeException("Failed to freeze configuration for resource " + resourceId); ++ } ++ return; ++ } ++ ++ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) ++ public void unfreezeResourceConfiguration(Subject subject, int resourceId) { ++ Query q = entityManager.createNamedQuery(Resource.UPDATE_UNSET_FROZEN_RES_CONFIG); ++ q.setParameter("id", resourceId); ++ int rows = q.executeUpdate(); ++ if (rows != 1) { ++ throw new RuntimeException("Failed to unfreeze configuration for resource " + resourceId); ++ } ++ return; ++ } ++ + @Nullable + public @XmlJavaTypeAdapter(ConfigurationAdapter.class) + Configuration getPluginConfiguration(Subject subject, int resourceId) { +@@ -292,6 +315,25 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf + return result; + } + ++ // Use new transaction because this only works if the resource in question has not ++ // yet been loaded by Hibernate. We want the query to return a non-proxied configuration, ++ // this is critical for remote API use. ++ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) ++ public Configuration getFrozenResourceConfiguration(int resourceId) { ++ // Ensure that we return a non-proxied Configuration object that can survive after the ++ // Hibernate session goes away. ++ Query query = entityManager.createNamedQuery(Configuration.QUERY_GET_FROZEN_RESOURCE_CONFIG_BY_RESOURCE_ID); ++ query.setParameter("resourceId", resourceId); ++ Configuration result; ++ try { ++ result = (Configuration) query.getSingleResult(); ++ } catch (NoResultException nre) { ++ result = null; ++ } ++ ++ return result; ++ } ++ + @Nullable + public ResourceConfigurationUpdate getLatestResourceConfigurationUpdate(Subject subject, int resourceId) { + log.debug("Getting current resource configuration for resource [" + resourceId + "]"); +diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerLocal.java +index f96a454..6c48837 100644 +--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerLocal.java ++++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerLocal.java +@@ -18,8 +18,15 @@ + */ + package org.rhq.enterprise.server.configuration; + ++import java.util.Collection; ++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; +@@ -41,11 +48,6 @@ import org.rhq.core.domain.util.PageList; + import org.rhq.enterprise.server.configuration.job.GroupPluginConfigurationUpdateJob; + import org.rhq.enterprise.server.resource.ResourceNotFoundException; + +-import javax.ejb.Local; +-import java.util.Collection; +-import java.util.List; +-import java.util.Map; +- + /** + * The configuration manager which allows you to request resource configuration changes, view current resource + * configuration and previous update history and view/edit plugin configuration. +@@ -56,6 +58,10 @@ import java.util.Map; + @Local + public interface ConfigurationManagerLocal { + ++ void freezeResourceConfiguration(Subject subject, int resourceId, int configUpdateId); ++ ++ void unfreezeResourceConfiguration(Subject subject, int resourceId); ++ + /** + * 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 +@@ -80,6 +86,12 @@ public interface ConfigurationManagerLocal { + */ + Configuration getResourceConfiguration(int resourceId); + ++ /** This does not perform permission checks and should be used internally only. In general, use ++ * {@link #getCurrentResourceConfiguration}. ++ * @throws FetchException TODO ++ */ ++ Configuration getFrozenResourceConfiguration(int resourceId); ++ + /** + * Get the currently live resource configuration for the {@link Resource} with the given id. This actually asks for + * the up-to-date configuration directly from the agent. An exception will be thrown if communications with the +diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationServerServiceImpl.java +index 8932607..91dc3fa 100644 +--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationServerServiceImpl.java ++++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationServerServiceImpl.java +@@ -64,11 +64,11 @@ public class ConfigurationServerServiceImpl implements ConfigurationServerServic + } + + public void persistUpdatedResourceConfiguration(int resourceId, Configuration resourceConfiguration) { +- ConfigurationManagerLocal configurationManager = LookupUtil.getConfigurationManager(); ++ final ConfigurationManagerLocal configurationManager = LookupUtil.getConfigurationManager(); + SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager(); + ResourceManagerLocal resourceManager = LookupUtil.getResourceManager(); + +- Subject overlord = subjectManager.getOverlord(); ++ final Subject overlord = subjectManager.getOverlord(); + ResourceConfigurationUpdate update = configurationManager.persistNewResourceConfigurationUpdateHistory( + overlord, resourceId, resourceConfiguration, ConfigurationUpdateStatus.SUCCESS, null, false); + +@@ -80,8 +80,26 @@ public class ConfigurationServerServiceImpl implements ConfigurationServerServic + } + } + +- Resource resource = update.getResource(); ++ final Resource resource = update.getResource(); + resource.setResourceConfiguration(update.getConfiguration().deepCopy(false)); + resourceManager.updateResource(overlord, resource); ++ ++ final Configuration frozen = configurationManager.getFrozenResourceConfiguration(resourceId); ++ if (frozen != null && !frozen.equals(resourceConfiguration)) { ++ // this resource has been frozen and the agent is trying to change it! revert back immediately! ++ new Thread(new Runnable() { ++ public void run() { ++ try { ++ Thread.sleep(5000L); ++ } catch (InterruptedException e) { ++ } ++ try { ++ configurationManager.updateResourceConfiguration(overlord, resource.getId(), frozen); ++ } catch (Exception e) { ++ LOG.error("cannot revert configuration back to its frozen state for resource : " + resource); ++ } ++ } ++ }, "RHQ Revert To Frozen Config For Resource " + resourceId).start(); ++ } + } + } +\ No newline at end of file +-- +1.6.2.5 + + +From 2e23715078139c5110439c5b9f2abbfaac05a834 Mon Sep 17 00:00:00 2001 +From: John Mazzitelli +Date: Tue, 1 Dec 2009 16:14:05 -0500 +Subject: [PATCH 2/3] get frozen config to take effect if we view live config and its different than the frozen config + +--- + .../configuration/ConfigurationManagerBean.java | 23 ++++++++++++++++++++ + 1 files changed, 23 insertions(+), 0 deletions(-) + +diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java +index b61a522..b87ac56 100644 +--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java ++++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java +@@ -426,6 +426,29 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf + this.subjectManager.getOverlord(), resource.getId(), liveConfig, ConfigurationUpdateStatus.SUCCESS, null, + false); + resource.setResourceConfiguration(liveConfig.deepCopy(false)); ++ ++ Configuration frozen = getFrozenResourceConfiguration(resource.getId()); ++ if (frozen != null && !frozen.equals(resource.getResourceConfiguration())) { ++ try { ++ Subject overlord = subjectManager.getOverlord(); ++ update = persistNewResourceConfigurationUpdateHistory(overlord, resource.getId(), frozen, ++ ConfigurationUpdateStatus.INPROGRESS, overlord.getName(), false); ++ resource.setResourceConfiguration(frozen); ++ final ResourceConfigurationUpdate updateToPush = update; ++ new Thread(new Runnable() { ++ public void run() { ++ try { ++ Thread.sleep(5000L); ++ } catch (InterruptedException e) { ++ } ++ executeResourceConfigurationUpdate(updateToPush); ++ } ++ }, "RHQ Frozen Config Revert For Resource " + resource.getName()).start(); ++ } catch (Exception e) { ++ log.error("cannot revert configuration back to its frozen state for resource : " + resource); ++ } ++ } ++ + return update; + } + +-- +1.6.2.5 + + +From 3e380264a1220ba6e5270fb807f54117742a5348 Mon Sep 17 00:00:00 2001 +From: John Mazzitelli +Date: Tue, 1 Dec 2009 16:14:44 -0500 +Subject: [PATCH 3/3] more frozen config changes + +--- + .../GetLatestConfigurationUpdateUIBean.java | 16 ++++++++++++++++ + .../rhq/resource/configuration/history.xhtml | 2 ++ + .../ConfigurationServerServiceImpl.java | 4 ++-- + 3 files changed, 20 insertions(+), 2 deletions(-) + +diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/history/GetLatestConfigurationUpdateUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/history/GetLatestConfigurationUpdateUIBean.java +index fb397a2..892b74b 100644 +--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/history/GetLatestConfigurationUpdateUIBean.java ++++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/history/GetLatestConfigurationUpdateUIBean.java +@@ -20,6 +20,7 @@ package org.rhq.enterprise.gui.configuration.history; + + 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.resource.Resource; + import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility; + import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal; +@@ -27,6 +28,8 @@ import org.rhq.enterprise.server.util.LookupUtil; + + public class GetLatestConfigurationUpdateUIBean { + private AbstractResourceConfigurationUpdate latestConfigurationUpdate = null; ++ private Configuration frozenConfiguration = null; ++ private Boolean frozenConfigurationIsNull = null; + + public AbstractResourceConfigurationUpdate getLatestConfigurationUpdate() { + if (latestConfigurationUpdate == null) { +@@ -39,4 +42,17 @@ public class GetLatestConfigurationUpdateUIBean { + + return latestConfigurationUpdate; + } ++ ++ public Configuration getFrozenConfiguration() { ++ if (frozenConfiguration == null) { ++ // TODO need a frozeConfigurationIsNull check ++ Resource resource = EnterpriseFacesContextUtility.getResource(); ++ ConfigurationManagerLocal manager = LookupUtil.getConfigurationManager(); ++ ++ frozenConfiguration = manager.getFrozenResourceConfiguration(resource.getId()); ++ frozenConfigurationIsNull = Boolean.valueOf(frozenConfiguration == null); ++ } ++ ++ return frozenConfiguration; ++ } + } +\ No newline at end of file +diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/configuration/history.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/configuration/history.xhtml +index 0b126bf..89522ed 100644 +--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/configuration/history.xhtml ++++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/configuration/history.xhtml +@@ -21,6 +21,7 @@ + + + ++ + + + +@@ -113,6 +114,7 @@ + + + ++ + + +diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationServerServiceImpl.java +index 91dc3fa..c8b8ce6 100644 +--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationServerServiceImpl.java ++++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationServerServiceImpl.java +@@ -72,8 +72,8 @@ public class ConfigurationServerServiceImpl implements ConfigurationServerServic + ResourceConfigurationUpdate update = configurationManager.persistNewResourceConfigurationUpdateHistory( + overlord, resourceId, resourceConfiguration, ConfigurationUpdateStatus.SUCCESS, null, false); + +- if (LOG.isDebugEnabled()) { +- if (update == null) { ++ if (update == null) { ++ if (LOG.isDebugEnabled()) { + LOG.debug("Not persisting Configuration " + resourceConfiguration + + ", since it is identical to the current revision."); + return; +-- +1.6.2.5 + -- cgit