modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/metadata/PluginMetadataManager.java | 5 modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java | 154 +++ modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeResponse.java | 80 + modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java | 12 modules/core/dbutils/src/main/scripts/dbsetup/sysconfig-data.xml | 3 modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceErrorType.java | 7 modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java | 121 ++ modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceErrorTest.java | 4 modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java | 89 + modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java | 45 modules/core/plugin-container/pom.xml | 146 ++ modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java | 2 modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/AutoDiscoveryExecutor.java | 2 modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java | 470 +++++++-- modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/RuntimeDiscoveryExecutor.java | 7 modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginComponentFactory.java | 15 modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/DiscoverySuspendedException.java | 50 + modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java | 267 +++++ modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/DiscoveryComponentProxyFactory.java | 10 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java | 352 +++++++ modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ForwardingProxy.java | 72 + modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java | 493 ++++++++++ modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java | 331 ++++++ modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java | 413 ++++++++ modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/DiscComponent.java | 70 + modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/ResComponent.java | 46 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/rhq-plugin.xml | 18 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseDiscoveryComponent.java | 80 + modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponent.java | 118 ++ modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponentInterface.java | 36 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java | 68 + modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/NothingDiscoveringDiscoveryComponent.java | 42 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/rhq-plugin.xml | 39 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/rhq-plugin.xml | 32 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/rhq-plugin.xml | 31 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml | 32 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml | 31 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/root/rhq-plugin.xml | 25 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml | 28 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml | 25 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml | 45 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml | 43 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/DiscComponent.java | 22 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/ResComponent.java | 21 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/rhq-plugin.xml | 18 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/DiscComponent.java | 54 + modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/ResComponent.java | 21 modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/rhq-plugin.xml | 18 modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java | 42 modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java | 3 modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/DiscoveryPromptCommand.java | 2 modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/PluginContainerConditionalRestart.java | 31 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java | 5 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewForm.java | 299 ++++++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java | 327 +----- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ResourceErrorsDataSource.java | 100 ++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java | 5 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java | 9 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/config/SystemConfigForm.java | 15 modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties | 2 modules/enterprise/gui/portal-war/src/main/webapp/admin/config/GeneralPropertiesConfigForm.jsp | 104 -- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/RHQConstants.java | 3 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java | 111 ++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java | 14 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java | 8 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java | 34 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java | 13 modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java | 152 +-- 68 files changed, 4835 insertions(+), 557 deletions(-)
New commits: commit 4969aa53cf7f5ff45fbb1510d2f110560f3f6a8f Merge: 065319e... 1b86f3a... Author: Lukas Krejci lkrejci@redhat.com Date: Tue Oct 5 14:18:01 2010 +0200
Merge branch '_resource-upgrade' into resource-upgrade
commit 1b86f3abaf44ebb4e0d62cb75a559b130500cd9f Author: Lukas Krejci lkrejci@redhat.com Date: Tue Oct 5 14:17:46 2010 +0200
BZ 593270 - the new style resource key for apache is <server-root>||<httpd-conf>. Implemented the ResourceUpgradeFacet to upgrade existing resources to that new format.
diff --git a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java index 660f727..ca8f972 100644 --- a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java +++ b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java @@ -170,38 +170,24 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen
public ResourceUpgradeReport upgrade(ResourceUpgradeContext<PlatformComponent> context) { String inventoriedResourceKey = context.getResourceKey(); - File inventoriedResourceKeyAsPath = new File(inventoriedResourceKey);
- //the resource key we use now is a full path to the httpd.conf. - //in the old version, it was the server root. - //so if the inventoried resource key is a path to a file, - //we know it's a new style resource key. - if (inventoriedResourceKeyAsPath.isFile()) { + //check if the inventoried resource has the old format of the resource key. + //the old format was "server-root", while the new format + //is "server-root||httpd-conf". Checking for "||" in the resource key is therefore + //enough. + if (inventoriedResourceKey.contains("||")) { return null; } + + //all the information we need for the new style resource key is + //actually present in the plugin configuration of the existing resource + //already, so let's just generate the new style resource key from it. + String resourceKey = formatResourceKey(context.getPluginConfiguration());
- Configuration pluginConfiguration = context.getPluginConfiguration(); + ResourceUpgradeReport rep = new ResourceUpgradeReport(); + rep.setNewResourceKey(resourceKey);
- String serverRoot = pluginConfiguration.getSimpleValue("serverRoot", null); - String httpdConf = pluginConfiguration.getSimpleValue("configFile", null); - - String resourceKey = null; - - if (httpdConf != null) { - File httpdConfFile = new File(httpdConf); - if (!httpdConfFile.isAbsolute()) { - httpdConfFile = new File(serverRoot, httpdConf); - } - - resourceKey = httpdConfFile.getPath(); - - ResourceUpgradeReport rep = new ResourceUpgradeReport(); - rep.setNewResourceKey(resourceKey); - - return rep; - } - - return null; + return rep; }
public DiscoveredResourceDetails discoverResource(Configuration pluginConfig, @@ -256,15 +242,7 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen name = uri.getHost() + ":" + uri.getPort(); }
- String serverRoot = pluginConfig.getSimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_SERVER_ROOT) - .getStringValue(); - - String key = FileUtils.getCanonicalPath(serverRoot); - - //BZ 612189 - reverting to the serverRoot as the resource key temporarily until we have the resource - //upgrade functionality ready (BZ 592038). Uncommenting the line below will make the resource key totally unique - //(see BZ 593270). - //key += "|" + httpdConf; + String key = formatResourceKey(pluginConfig);
DiscoveredResourceDetails resourceDetails = new DiscoveredResourceDetails(discoveryContext.getResourceType(), key, name, version, PRODUCT_DESCRIPTION, pluginConfig, processInfo); @@ -455,4 +433,14 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen } return null; } + + private static String formatResourceKey(Configuration pluginConfiguration) { + String serverRoot = pluginConfiguration.getSimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_SERVER_ROOT).getStringValue(); + String httpdConf = pluginConfiguration.getSimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_HTTPD_CONF).getStringValue(); + + serverRoot = FileUtils.getCanonicalPath(serverRoot); + httpdConf = FileUtils.getCanonicalPath(httpdConf); + + return serverRoot + "||" + httpdConf; + } }
commit a0edcceda8b63f23cc6570fb1da34251f245f3c0 Author: Lukas Krejci lkrejci@redhat.com Date: Tue Oct 5 13:35:57 2010 +0200
code formatting
diff --git a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java index c305ec4..660f727 100644 --- a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java +++ b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java @@ -21,18 +21,14 @@ package org.rhq.plugins.apache; import java.io.File; import java.io.IOException; import java.net.URI; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.rhq.augeas.node.AugeasNode; -import org.rhq.augeas.tree.AugeasTree; import org.rhq.augeas.util.Glob; import org.rhq.augeas.util.GlobFilter; import org.rhq.core.domain.configuration.Configuration; @@ -45,7 +41,6 @@ import org.rhq.core.pluginapi.inventory.ManualAddFacet; import org.rhq.core.pluginapi.inventory.ProcessScanResult; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; -import org.rhq.core.pluginapi.inventory.ManualAddFacet; import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; import org.rhq.core.pluginapi.util.FileUtils; @@ -58,8 +53,8 @@ import org.rhq.plugins.apache.parser.ApacheParserImpl; import org.rhq.plugins.apache.util.ApacheBinaryInfo; import org.rhq.plugins.apache.util.AugeasNodeValueUtil; import org.rhq.plugins.apache.util.HttpdAddressUtility; -import org.rhq.plugins.apache.util.OsProcessUtility; import org.rhq.plugins.apache.util.HttpdAddressUtility.Address; +import org.rhq.plugins.apache.util.OsProcessUtility; import org.rhq.plugins.platform.PlatformComponent; import org.rhq.rhqtransform.impl.PluginDescriptorBasedAugeasConfiguration;
@@ -69,13 +64,14 @@ import org.rhq.rhqtransform.impl.PluginDescriptorBasedAugeasConfiguration; * @author Ian Springer * @author Lukas Krejci */ -public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponent<PlatformComponent>, ManualAddFacet<PlatformComponent>, - ResourceUpgradeFacet<PlatformComponent> { +public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponent<PlatformComponent>, + ManualAddFacet<PlatformComponent>, ResourceUpgradeFacet<PlatformComponent> { private static final String PRODUCT_DESCRIPTION = "Apache Web Server";
private static final Log log = LogFactory.getLog(ApacheServerDiscoveryComponent.class);
- public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<PlatformComponent> discoveryContext) throws Exception { + public Set<DiscoveredResourceDetails> + discoverResources(ResourceDiscoveryContext<PlatformComponent> discoveryContext) throws Exception { Set<DiscoveredResourceDetails> discoveredResources = new HashSet<DiscoveredResourceDetails>();
// Process any PC-discovered OS processes... @@ -89,16 +85,16 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen continue; } if (!executablePath.isAbsolute()) { - log.error("Executable path (" + executablePath + ") is not absolute for Apache [" + - process.getProcessInfo() + "]." + - "Please restart Apache specifying an absolute path for the executable."); + log.error("Executable path (" + executablePath + ") is not absolute for Apache [" + + process.getProcessInfo() + "]." + + "Please restart Apache specifying an absolute path for the executable."); continue; } log.debug("Apache executable path: " + executablePath); ApacheBinaryInfo binaryInfo; try { - binaryInfo = ApacheBinaryInfo.getInfo(executablePath.getPath(), - discoveryContext.getSystemInformation()); + binaryInfo = ApacheBinaryInfo + .getInfo(executablePath.getPath(), discoveryContext.getSystemInformation()); } catch (Exception e) { log.error("'" + executablePath + "' is not a valid Apache executable (" + e + ")."); continue; @@ -130,38 +126,40 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen PropertySimple configFile = new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_HTTPD_CONF, serverConfigFile); pluginConfig.put(configFile); - - PropertySimple inclusionGlobs = new PropertySimple(PluginDescriptorBasedAugeasConfiguration.INCLUDE_GLOBS_PROP, serverConfigFile); + + PropertySimple inclusionGlobs = new PropertySimple( + PluginDescriptorBasedAugeasConfiguration.INCLUDE_GLOBS_PROP, serverConfigFile); pluginConfig.put(inclusionGlobs); - - ApacheDirectiveTree serverConfig = loadParser(serverConfigFile.getAbsolutePath(),serverRoot); - + + ApacheDirectiveTree serverConfig = loadParser(serverConfigFile.getAbsolutePath(), serverRoot); + String serverUrl = null; String vhostsGlobInclude = null; - + //now check if the httpd.conf doesn't redefine the ServerRoot List<ApacheDirective> serverRoots = serverConfig.search("/ServerRoot"); if (!serverRoots.isEmpty()) { serverRoot = AugeasNodeValueUtil.unescape(serverRoots.get(0).getValuesAsString()); serverRootProp.setValue(serverRoot); - } + } + + serverUrl = getUrl(serverConfig, binaryInfo.getVersion()); + vhostsGlobInclude = scanForGlobInclude(serverConfig);
- serverUrl = getUrl(serverConfig, binaryInfo.getVersion()); - vhostsGlobInclude = scanForGlobInclude(serverConfig); - if (serverUrl != null) { Property urlProp = new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_URL, serverUrl); - pluginConfig.put(urlProp); + pluginConfig.put(urlProp); } - + if (vhostsGlobInclude != null) { - pluginConfig.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_VHOST_FILES_MASK, vhostsGlobInclude)); - }else - { + pluginConfig.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_VHOST_FILES_MASK, + vhostsGlobInclude)); + } else { if (serverConfigFile.exists()) - pluginConfig.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_VHOST_FILES_MASK, serverConfigFile.getParent()+File.separator+"*")); + pluginConfig.put(new PropertySimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_VHOST_FILES_MASK, + serverConfigFile.getParent() + File.separator + "*")); } - + discoveredResources.add(createResourceDetails(discoveryContext, pluginConfig, process.getProcessInfo(), binaryInfo)); } @@ -202,18 +200,16 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen
return rep; } - + return null; }
public DiscoveredResourceDetails discoverResource(Configuration pluginConfig, - ResourceDiscoveryContext<PlatformComponent> discoveryContext) - throws InvalidPluginConfigurationException { + ResourceDiscoveryContext<PlatformComponent> discoveryContext) throws InvalidPluginConfigurationException { validateServerRootAndServerConfigFile(pluginConfig);
- String executablePath = pluginConfig - .getSimpleValue(ApacheServerComponent.PLUGIN_CONFIG_PROP_EXECUTABLE_PATH, - ApacheServerComponent.DEFAULT_EXECUTABLE_PATH); + String executablePath = pluginConfig.getSimpleValue(ApacheServerComponent.PLUGIN_CONFIG_PROP_EXECUTABLE_PATH, + ApacheServerComponent.DEFAULT_EXECUTABLE_PATH); String absoluteExecutablePath = ApacheServerComponent.resolvePathRelativeToServerRoot(pluginConfig, executablePath).getPath(); ApacheBinaryInfo binaryInfo; @@ -222,13 +218,12 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen } catch (Exception e) { throw new InvalidPluginConfigurationException("'" + absoluteExecutablePath + "' is not a valid Apache executable (" + e + "). Please make sure the '" - + ApacheServerComponent.PLUGIN_CONFIG_PROP_EXECUTABLE_PATH - + "' connection property is set correctly."); + + ApacheServerComponent.PLUGIN_CONFIG_PROP_EXECUTABLE_PATH + "' connection property is set correctly."); }
if (!isSupportedVersion(binaryInfo.getVersion())) { - throw new InvalidPluginConfigurationException("Version of Apache executable (" - + binaryInfo.getVersion() + ") is not a supported version; supported versions are 1.3.x and 2.x."); + throw new InvalidPluginConfigurationException("Version of Apache executable (" + binaryInfo.getVersion() + + ") is not a supported version; supported versions are 1.3.x and 2.x."); }
ProcessInfo processInfo = null; @@ -236,8 +231,7 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen DiscoveredResourceDetails resourceDetails = createResourceDetails(discoveryContext, pluginConfig, processInfo, binaryInfo); return resourceDetails; - } - catch (Exception e) { + } catch (Exception e) { throw new RuntimeException("Failed to create resource details during manual add."); } } @@ -247,8 +241,9 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen return (version != null) && (version.startsWith("1.3") || version.startsWith("2.")); }
- private DiscoveredResourceDetails createResourceDetails(ResourceDiscoveryContext<PlatformComponent> discoveryContext, - Configuration pluginConfig, ProcessInfo processInfo, ApacheBinaryInfo binaryInfo) throws Exception { + private DiscoveredResourceDetails createResourceDetails( + ResourceDiscoveryContext<PlatformComponent> discoveryContext, Configuration pluginConfig, + ProcessInfo processInfo, ApacheBinaryInfo binaryInfo) throws Exception { String httpdConf = pluginConfig.getSimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_HTTPD_CONF).getStringValue(); String version = binaryInfo.getVersion(); String serverUrl = pluginConfig.getSimpleValue(ApacheServerComponent.PLUGIN_CONFIG_PROP_URL, null); @@ -258,19 +253,19 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen name = httpdConf; } else { URI uri = new URI(serverUrl); - name = uri.getHost() + ":" + uri.getPort(); + name = uri.getHost() + ":" + uri.getPort(); }
String serverRoot = pluginConfig.getSimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_SERVER_ROOT) .getStringValue(); - + String key = FileUtils.getCanonicalPath(serverRoot);
//BZ 612189 - reverting to the serverRoot as the resource key temporarily until we have the resource //upgrade functionality ready (BZ 592038). Uncommenting the line below will make the resource key totally unique //(see BZ 593270). //key += "|" + httpdConf; - + DiscoveredResourceDetails resourceDetails = new DiscoveredResourceDetails(discoveryContext.getResourceType(), key, name, version, PRODUCT_DESCRIPTION, pluginConfig, processInfo); log.debug("Apache Server resource details created: " + resourceDetails); @@ -290,7 +285,6 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen return addr == null ? null : "http://" + addr.host + ":" + addr.port + "/"; }
- @Nullable private String getServerRoot(@NotNull ApacheBinaryInfo binaryInfo, @NotNull ProcessInfo processInfo) { // First see if -d was specified on the httpd command line. @@ -315,12 +309,12 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen currentWorkingDir = processInfo.getCurrentWorkingDirectory(); } catch (Exception e) { log.error("Unable to determine current working directory of Apache process [" + processInfo - + "], which is needed to determine the server root of the Apache instance.", e); + + "], which is needed to determine the server root of the Apache instance.", e); return null; } if (currentWorkingDir == null) { log.error("Unable to determine current working directory of Apache process [" + processInfo - + "], which is needed to determine the server root of the Apache instance."); + + "], which is needed to determine the server root of the Apache instance."); return null; } else { rootFile = new File(currentWorkingDir, root); @@ -396,12 +390,12 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen }
private static void validateServerRootAndServerConfigFile(Configuration pluginConfig) { - String serverRoot = pluginConfig.getSimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_SERVER_ROOT).getStringValue(); + String serverRoot = pluginConfig.getSimple(ApacheServerComponent.PLUGIN_CONFIG_PROP_SERVER_ROOT) + .getStringValue(); File serverRootFile; try { serverRootFile = new File(serverRoot).getCanonicalFile(); // this will resolve symlinks - } - catch (IOException e) { + } catch (IOException e) { serverRootFile = null; } if (serverRootFile == null || !serverRootFile.isDirectory()) { @@ -413,8 +407,7 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen File httpdConfFile; try { httpdConfFile = new File(httpdConf).getCanonicalFile(); // this will resolve symlinks - } - catch (IOException e) { + } catch (IOException e) { httpdConfFile = null; } if (httpdConfFile == null || !httpdConfFile.isFile()) { @@ -423,15 +416,15 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen + ApacheServerComponent.PLUGIN_CONFIG_PROP_HTTPD_CONF + "' connection property is set correctly."); } } - - private static ApacheDirectiveTree loadParser(String path,String serverRoot) throws Exception{ + + private static ApacheDirectiveTree loadParser(String path, String serverRoot) throws Exception {
ApacheDirectiveTree tree = new ApacheDirectiveTree(); - ApacheParser parser = new ApacheParserImpl(tree,serverRoot); + ApacheParser parser = new ApacheParserImpl(tree, serverRoot); ApacheConfigReader.buildTree(path, parser); return tree; } - + public static String scanForGlobInclude(ApacheDirectiveTree tree) { try { List<ApacheDirective> includes = tree.search("/Include"); @@ -440,9 +433,9 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen if (Glob.isWildcard(include)) { //we only take the '*.something' into account here //so that we have a useful mask to base the file names on. - + //the only special glob character allowed is *. - for(char specialChar : GlobFilter.WILDCARD_CHARS) { + for (char specialChar : GlobFilter.WILDCARD_CHARS) { if (specialChar == '*') { if (include.indexOf(specialChar) != include.lastIndexOf(specialChar)) { //more than 1 star... that's too much @@ -462,4 +455,4 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen } return null; } -} \ No newline at end of file +}
commit 065319e2048376d93509e31dd526789b26947b4f Merge: 98a4d17... 297cc73... Author: Lukas Krejci lkrejci@redhat.com Date: Tue Oct 5 12:49:38 2010 +0200
Merge branch 'master' into resource-upgrade
commit 98a4d17665d0fed83e0fd2c28770545178b00150 Author: Lukas Krejci lkrejci@redhat.com Date: Tue Oct 5 12:48:12 2010 +0200
making the getResourcesWithType(ResourceType, Set<Resource>) private again.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index c5004dd..351f751 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -1668,7 +1668,7 @@ public class InventoryManager extends AgentService implements ContainerService, return getResourcesWithType(serverType, this.platform.getChildResources()); }
- public Set<Resource> getResourcesWithType(ResourceType serverType, Set<Resource> resources) { + private Set<Resource> getResourcesWithType(ResourceType serverType, Set<Resource> resources) { Set<Resource> servers = new HashSet<Resource>();
if (resources == null) {
commit 98ab21b9a9348520b30fae149d67d39af7553373 Author: Lukas Krejci lkrejci@redhat.com Date: Mon Oct 4 18:58:14 2010 +0200
Getting the InventoryManager.handleReport(InventoryReport) inline with the version in master, updating the upgrade tests to accommodate for the changed behavior.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index ec40b0c..c5004dd 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -932,30 +932,16 @@ public class InventoryManager extends AgentService implements ContainerService, }
/** - * @see #handleReport(InventoryReport, boolean) - * @param report - * @return - */ - public boolean handleReport(InventoryReport report) { - return handleReport(report, false); - } - - /** * Send an inventory report to the Server. * * @param report the inventory report to be sent - * @param forceServerRoundtrip whether to report to the server even if there are no resources to report. * @return true if sending the report to the Server succeeded, or false otherwise */ - public boolean handleReport(InventoryReport report, boolean forceServerRoundtrip) { + public boolean handleReport(InventoryReport report) { if (!configuration.isInsideAgent()) { return true; }
- if (report.getAddedRoots().isEmpty() && !forceServerRoundtrip) { - return true; // nothing to do - } - ResourceSyncInfo syncInfo; try { String reportType = (report.isRuntimeReport()) ? "runtime" : "server"; @@ -2659,7 +2645,7 @@ public class InventoryManager extends AgentService implements ContainerService,
log.debug("Executing resource upgrade.");
- boolean syncResult = handleReport(new InventoryReport(getAgent()), true); + boolean syncResult = handleReport(new InventoryReport(getAgent())); if (!syncResult) { log.warn("Resource upgrade failed to sync up the inventory with the server."); return; diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java index ebb73be..ab1cd2b 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java @@ -342,10 +342,6 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase expectations.allowing(getCurrentDiscoveryServerService()).upgradeResources( expectations.with(Expectations.any(Set.class))); expectations.will(getCurrentServerSideInventory().upgradeResources()); - - expectations.allowing(getCurrentDiscoveryServerService()).postProcessNewlyCommittedResources( - expectations.with(Expectations.any(Set.class))); - } catch (InvalidInventoryReportException e) { //this is not going to happen because we're mocking the invocation } diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index 8b966c3..e2a8a84 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -93,7 +93,7 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { { defineDefaultExpectations(this);
- between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + allowing(getCurrentDiscoveryServerService()).mergeInventoryReport( with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
@@ -144,7 +144,7 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { { defineDefaultExpectations(this);
- between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + allowing(getCurrentDiscoveryServerService()).mergeInventoryReport( with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
@@ -197,7 +197,7 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase {
//the rest of the inventory merges are executed by discoveries, so let's import the //discovered stuff into the server-side inventory. - between(1, 3).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + allowing(getCurrentDiscoveryServerService()).mergeInventoryReport( with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
@@ -242,7 +242,7 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { { defineDefaultExpectations(this);
- between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + allowing(getCurrentDiscoveryServerService()).mergeInventoryReport( with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
@@ -276,7 +276,7 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { { defineDefaultExpectations(this);
- between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + allowing(getCurrentDiscoveryServerService()).mergeInventoryReport( with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(requiredInventoryStatus)); } @@ -317,7 +317,7 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { { defineDefaultExpectations(this);
- between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + allowing(getCurrentDiscoveryServerService()).mergeInventoryReport( with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java index 0aefafd..c299cce 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java @@ -402,6 +402,9 @@ public abstract class ResourceUpgradeTestBase { expectations.allowing(getCurrentDiscoveryServerService()).getResources( expectations.with(Expectations.any(Set.class)), expectations.with(Expectations.any(boolean.class))); expectations.will(getCurrentServerSideInventory().getResources()); + + expectations.allowing(getCurrentDiscoveryServerService()).postProcessNewlyCommittedResources( + expectations.with(Expectations.any(Set.class))); }
protected void cleanDataDir() throws IOException {
commit 65c3b23735a092f9675cb2e878b79039b5ab9c93 Merge: e7fb6ed... ebd4ec6... Author: Lukas Krejci lkrejci@redhat.com Date: Mon Oct 4 18:37:55 2010 +0200
Merge branch 'master' into resource-upgrade
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java index 150a692,4e14b75..a004680 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java @@@ -238,11 -274,11 +275,15 @@@ public class ResourceGWTServiceImpl ext }
public void unignoreResources(Integer[] resourceIds) { - discoveryBoss.unignoreResources(getSessionSubject(), resourceIds); + try { + discoveryBoss.unignoreResources(getSessionSubject(), resourceIds); + } catch (Exception e) { + throw new RuntimeException(ThrowableUtil.getAllMessages(e)); + } } - -} + + public List<ResourceError> findResourceErrors(int resourceId) { + return SerialUtility.prepare(resourceManager.findResourceErrors(getSessionSubject(), resourceId), + "ResourceService.getResourceErrors"); + } +}
commit e7fb6edacd4c172a236cfc39b19096f03cef85ee Author: Lukas Krejci lkrejci@redhat.com Date: Mon Oct 4 18:34:25 2010 +0200
Discovery now recurses to child resource types of the existing resources even if the discovery of the existing resources' type is disallowed due to upgrade failure. This means that no new siblings will be discovered but the existing resources "contents" will be up-to-date with the plugin version.
Added tests for this behaviour and updated the existing to reflect the changes.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 99a0513..ec40b0c 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -91,6 +91,7 @@ import org.rhq.core.pc.plugin.BlacklistedException; import org.rhq.core.pc.plugin.CanonicalResourceKey; import org.rhq.core.pc.plugin.PluginComponentFactory; import org.rhq.core.pc.plugin.PluginManager; +import org.rhq.core.pc.upgrade.DiscoverySuspendedException; import org.rhq.core.pc.upgrade.ResourceUpgradeDelegate; import org.rhq.core.pc.util.DiscoveryComponentProxyFactory; import org.rhq.core.pc.util.FacetLockType; @@ -289,18 +290,22 @@ public class InventoryManager extends AgentService implements ContainerService, * @param context the context for use by the discovery component * @return the details of all discovered resources, may be empty or <code>null</code> * + * @throws DiscoverySuspendedException if the discovery is suspended due to a resource upgrade failure * @throws Exception if the discovery component threw an exception */ public Set<DiscoveredResourceDetails> invokeDiscoveryComponent(ResourceContainer parentResourceContainer, - ResourceDiscoveryComponent component, ResourceDiscoveryContext context) throws Exception { + ResourceDiscoveryComponent component, ResourceDiscoveryContext context) throws DiscoverySuspendedException, Exception {
Resource parentResource = parentResourceContainer == null ? null : parentResourceContainer.getResource();
if (resourceUpgradeDelegate.hasUpgradeFailedInChildren(parentResource, context.getResourceType())) { - log.debug("Discovery of [" + context.getResourceType() + "] has been disallowed under " - + (parentResource == null ? " the platform " : parentResource) - + " because some of its siblings failed to upgrade."); - return null; + String message = "Discovery of [" + context.getResourceType() + "] has been suspended under " + + (parentResource == null ? " the platform " : parentResource) + + " because some of its siblings failed to upgrade."; + + log.debug(message); + + throw new DiscoverySuspendedException(message); }
long timeout = getDiscoveryComponentTimeout(context.getResourceType()); @@ -699,19 +704,29 @@ public class InventoryManager extends AgentService implements ContainerService,
// Ask the plugin's discovery component to find the new resource, throwing exceptions if it cannot be // found at all. - Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentResourceContainer, - discoveryComponent, discoveryContext); - if ((discoveredResources == null) || discoveredResources.isEmpty()) { - log.info("Plugin Error: During manual add, discovery component method [" - + discoveryComponent.getClass().getName() + ".discoverResources()] returned " - + discoveredResources + " when passed a single plugin configuration " - + "(either the resource type was blacklisted or the plugin developer " - + "did not implement support for manually discovered resources correctly)."); - throw new PluginContainerException("The [" + resourceType.getPlugin() - + "] plugin does not properly support manual addition of [" + resourceType.getName() - + "] resources."); + try { + Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentResourceContainer, + discoveryComponent, discoveryContext); + if ((discoveredResources == null) || discoveredResources.isEmpty()) { + log.info("Plugin Error: During manual add, discovery component method [" + + discoveryComponent.getClass().getName() + ".discoverResources()] returned " + + discoveredResources + " when passed a single plugin configuration " + + "(either the resource type was blacklisted or the plugin developer " + + "did not implement support for manually discovered resources correctly)."); + throw new PluginContainerException("The [" + resourceType.getPlugin() + + "] plugin does not properly support manual addition of [" + resourceType.getName() + + "] resources."); + } + discoveredResourceDetails = discoveredResources.iterator().next(); + } catch (DiscoverySuspendedException e) { + String message = "The discovery class [" + discoveryComponent.getClass().getName() + "]" + + " uses a legacy implementation of "manual add" functionality. Some of the child resources" + + " with the resource type [" + resourceType + "] under the parent resource [" + parentResourceContainer.getResource() + "]" + + " failed to upgrade, which makes it impossible to support the legacy manual-add implementation. Either upgrade the plugin [" + + resourceType.getPlugin() + "] to successfully upgrade all resources or consider implementing the ManuallAdd facet."; + log.info(message); + throw new PluginContainerException(message, e); } - discoveredResourceDetails = discoveredResources.iterator().next(); }
// Create the new Resource and add it to inventory if it isn't already there. @@ -1844,6 +1859,8 @@ public class InventoryManager extends AgentService implements ContainerService,
try { discoveredResources = invokeDiscoveryComponent(null, component, context); + } catch (DiscoverySuspendedException e) { + log.error("Discovery seems to be suspended for platforms due to upgrade error.", e); } catch (Throwable e) { log.warn("Platform plugin discovery failed - skipping", e); } @@ -2179,35 +2196,47 @@ public class InventoryManager extends AgentService implements ContainerService, parentResourceContext, SystemInfoFactory.createSystemInfo(), processScanResults, Collections.EMPTY_LIST, this.configuration.getContainerName(), this.configuration.getPluginContainerDeployment()); - Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentContainer, - discoveryComponent, context); newResources = new HashSet<Resource>(); - if ((discoveredResources != null) && (!discoveredResources.isEmpty())) { - IdentityHashMap<Configuration, DiscoveredResourceDetails> pluginConfigObjects = new IdentityHashMap<Configuration, DiscoveredResourceDetails>(); - for (DiscoveredResourceDetails discoveredResource : discoveredResources) { - if (discoveredResource == null) { - throw new IllegalStateException("Plugin error: Discovery class " - + discoveryComponent.getClass().getName() - + " returned a Set containing one or more null items."); - } - if (!discoveredResource.getResourceType().equals(resourceType)) { - throw new IllegalStateException("Plugin error: Discovery class " - + discoveryComponent.getClass().getName() - + " returned a DiscoveredResourceDetails with an incorrect ResourceType (was " - + discoveredResource.getResourceType().getName() + " but should have been " - + resourceType.getName()); + try { + Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentContainer, + discoveryComponent, context); + if ((discoveredResources != null) && (!discoveredResources.isEmpty())) { + IdentityHashMap<Configuration, DiscoveredResourceDetails> pluginConfigObjects = new IdentityHashMap<Configuration, DiscoveredResourceDetails>(); + for (DiscoveredResourceDetails discoveredResource : discoveredResources) { + if (discoveredResource == null) { + throw new IllegalStateException("Plugin error: Discovery class " + + discoveryComponent.getClass().getName() + + " returned a Set containing one or more null items."); + } + if (!discoveredResource.getResourceType().equals(resourceType)) { + throw new IllegalStateException("Plugin error: Discovery class " + + discoveryComponent.getClass().getName() + + " returned a DiscoveredResourceDetails with an incorrect ResourceType (was " + + discoveredResource.getResourceType().getName() + " but should have been " + + resourceType.getName()); + } + if (null != pluginConfigObjects + .put(discoveredResource.getPluginConfiguration(), discoveredResource)) { + throw new IllegalStateException("The plugin component " + + discoveryComponent.getClass().getName() + + " returned multiple resources that point to the same plugin configuration object on the " + + "resource type [" + resourceType + "]. This is not allowed, please use " + + "ResoureDiscoveryContext.getDefaultPluginConfiguration() " + + "for each discovered resource."); + } + Resource newResource = InventoryManager.createNewResource(discoveredResource); + newResources.add(newResource); } - if (null != pluginConfigObjects - .put(discoveredResource.getPluginConfiguration(), discoveredResource)) { - throw new IllegalStateException("The plugin component " - + discoveryComponent.getClass().getName() - + " returned multiple resources that point to the same plugin configuration object on the " - + "resource type [" + resourceType + "]. This is not allowed, please use " - + "ResoureDiscoveryContext.getDefaultPluginConfiguration() " - + "for each discovered resource."); + } + } catch (DiscoverySuspendedException e) { + //ok, the discovery is suspended for this resource type under this parent. + //but we can continue the discovery in the child resource types of the existing resources. + //we can therefore pretend that the discovery returned the existing resources so that + //we can recurse into their children up in the call-chain. + for(Resource existingResource : parentResource.getChildResources()) { + if (resourceType.equals(existingResource.getResourceType())) { + newResources.add(existingResource); } - Resource newResource = InventoryManager.createNewResource(discoveredResource); - newResources.add(newResource); } } } catch (Throwable e) { @@ -2654,14 +2683,14 @@ public class InventoryManager extends AgentService implements ContainerService, if (container != null) { if (container.getResourceComponentState() == ResourceComponentState.STARTED) { try { - resourceUpgradeDelegate.processAndQueue(container); + if (resourceUpgradeDelegate.processAndQueue(container)) { + for (Resource child : resource.getChildResources()) { + upgradeResource(child); + } + } } catch (PluginContainerException e) { log.error("Exception thrown while upgrading [" + resource + "].", e); } - - for (Resource child : resource.getChildResources()) { - upgradeResource(child); - } } else { String message = "The resource container for resource [" + resource + "] wasn't started while upgrading."; diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/DiscoverySuspendedException.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/DiscoverySuspendedException.java new file mode 100644 index 0000000..5cb695d --- /dev/null +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/DiscoverySuspendedException.java @@ -0,0 +1,50 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade; + +import org.rhq.core.pc.inventory.InventoryManager; + +/** + * This exception is thrown from the {@link InventoryManager#invokeDiscoveryComponent(org.rhq.core.pc.inventory.ResourceContainer, org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent, org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext)} if the + * discovery is suspended for given resource type due to a resource upgrade failure. + * + * @author Lukas Krejci + */ +public class DiscoverySuspendedException extends Exception { + + private static final long serialVersionUID = 1L; + + public DiscoverySuspendedException() { + super(); + } + + public DiscoverySuspendedException(String message, Throwable cause) { + super(message, cause); + } + + public DiscoverySuspendedException(String message) { + super(message); + } + + public DiscoverySuspendedException(Throwable cause) { + super(cause); + } + +} diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java index 98a897e..06d2cd0 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java @@ -26,6 +26,7 @@ import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.rhq.core.clientapi.agent.PluginContainerException; import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; import org.rhq.core.domain.resource.Resource; @@ -61,7 +62,7 @@ public class ResourceUpgradeDelegate { private Set<Resource> failedResources = new HashSet<Resource>(); private Map<Resource, Set<ResourceType>> failedResourceTypesPerParent = new HashMap<Resource, Set<ResourceType>>(); private boolean mergeFailed; - + public ResourceUpgradeDelegate(InventoryManager inventoryManager) { this.inventoryManager = inventoryManager; } @@ -84,13 +85,17 @@ public class ResourceUpgradeDelegate { /** * Asks the resource's discovery component to upgrade the resource. * @param resourceContainer - * @return true if the resource was queued for upgrade, false otherwise + * @return true if the resource was queued for upgrade with no problems, + * false if there was some problem upgrading and the resource container was deactivated as + * a results of that. * @throws PluginContainerException on error */ - public void processAndQueue(ResourceContainer resourceContainer) throws PluginContainerException { + public boolean processAndQueue(ResourceContainer resourceContainer) throws PluginContainerException { if (enabled) { - executeResourceUpgradeFacetAndStoreRequest(resourceContainer); + return executeResourceUpgradeFacetAndStoreRequest(resourceContainer); } + + return true; }
/** @@ -99,7 +104,7 @@ public class ResourceUpgradeDelegate { public boolean hasUpgradeMergeFailed() { return mergeFailed; } - + /** * Tells whether given resource had a upgrade failure during the {@link #processAndQueue(ResourceContainer)} invocation. * @@ -109,7 +114,7 @@ public class ResourceUpgradeDelegate { public boolean hasUpgradeFailed(Resource resource) { return mergeFailed || failedResources.contains(resource); } - + /** * Tells whether at least one of the children with given resource type of the given parent resource * had an upgrade failure during {@link #processAndQueue(ResourceContainer)} invocation. @@ -120,35 +125,35 @@ public class ResourceUpgradeDelegate { if (mergeFailed) { return true; } - + Set<ResourceType> failedTypes = failedResourceTypesPerParent.get(parentResource); - + return failedTypes != null && failedTypes.contains(childrenResourceType); } - + public void sendRequests() throws Throwable { if (enabled && requests.size() > 0) { try { inventoryManager.mergeResourcesFromUpgrade(requests); } catch (Throwable t) { mergeFailed = true; - + //deactivate all the resources to be upgraded. We might have a problem //because they have not been upgraded because the merge failed. - for(ResourceUpgradeRequest request : requests) { + for (ResourceUpgradeRequest request : requests) { ResourceContainer container = inventoryManager.getResourceContainer(request.getResourceId()); if (container != null) { inventoryManager.deactivateResource(container.getResource()); } } - + throw t; } } }
@SuppressWarnings("unchecked") - private <T extends ResourceComponent> void executeResourceUpgradeFacetAndStoreRequest( + private <T extends ResourceComponent> boolean executeResourceUpgradeFacetAndStoreRequest( ResourceContainer resourceContainer) throws PluginContainerException {
ResourceComponent<T> parentResourceComponent = resourceContainer.getResourceContext() @@ -166,16 +171,16 @@ public class ResourceUpgradeDelegate {
if (!(discoveryComponent instanceof ResourceUpgradeFacet)) { //well, there's no point in continuing if the resource doesn't support the facet - return; + return true; }
ResourceUpgradeContext<ResourceComponent<T>> upgradeContext = inventoryManager.createResourceUpgradeContext( resource, parentResourceComponent, discoveryComponent);
ResourceUpgradeRequest request = new ResourceUpgradeRequest(resource.getId()); - + request.setTimestamp(System.currentTimeMillis()); - + ResourceUpgradeReport upgradeReport = null; try { upgradeReport = inventoryManager.invokeDiscoveryComponentResourceUpgradeFacet(resource.getResourceType(), @@ -189,13 +194,13 @@ public class ResourceUpgradeDelegate { String upgradeErrors = null; if ((upgradeErrors = checkUpgradeValid(resource, upgradeReport)) != null) { String errorString = "Upgrading the resource [" + resource + "] using these updates [" + upgradeReport - + "] would render the inventory invalid because of the following reasons: " + upgradeErrors; - + + "] would render the inventory invalid because of the following reasons: " + upgradeErrors; + log.error(errorString); - + IllegalStateException ex = new IllegalStateException(errorString); ex.fillInStackTrace(); - + request.setErrorProperties(ex); } else { request.fillInFromReport(upgradeReport); @@ -207,20 +212,24 @@ public class ResourceUpgradeDelegate { if (request.hasSomethingToUpgrade()) { requests.add(request); } - + if (request.getUpgradeErrorMessage() != null) { failedResources.add(resource); - + Set<ResourceType> failedResourceTypesInParent = failedResourceTypesPerParent.get(parentResource); if (failedResourceTypesInParent == null) { failedResourceTypesInParent = new HashSet<ResourceType>(); failedResourceTypesPerParent.put(parentResource, failedResourceTypesInParent); } - + failedResourceTypesInParent.add(resource.getResourceType()); - + inventoryManager.deactivateResource(resource); + + return false; } + + return true; }
private String checkUpgradeValid(Resource resource, ResourceUpgradeReport upgradeReport) { diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java index 7eafafc..ebb73be 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java @@ -156,9 +156,9 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase
//check that the resources are upgraded checkResourcesUpgraded(resources.get(PARENT_DEP_SIBLING_TYPE), 1); - checkResourcesUpgraded(resources.get(PARENT_TYPE), 2); - checkResourcesUpgraded(resources.get(SIBLING_TYPE), 30); - checkResourcesUpgraded(resources.get(TEST_TYPE), 30); + checkResourcesUpgraded(resources.get(PARENT_TYPE), 3); + checkResourcesUpgraded(resources.get(SIBLING_TYPE), 45); + checkResourcesUpgraded(resources.get(TEST_TYPE), 45); }
public Expectations getExpectations(Mockery context) throws Exception { @@ -206,19 +206,24 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase
checkNumberOfResources(resources, ROOT_TYPE, 1); checkNumberOfResources(resources, PARENT_DEP_TYPE, 1); - checkNumberOfResources(resources, PARENT_TYPE, 2);
- checkResourcesUpgraded(resources.get(PARENT_TYPE), 2); + checkResourcesUpgraded(resources.get(PARENT_TYPE), 3); checkResourcesUpgraded(resources.get(PARENT_DEP_SIBLING_TYPE), 1);
Resource parent0 = findResourceWithOrdinal(PARENT_TYPE, 0); Resource parent1 = findResourceWithOrdinal(PARENT_TYPE, 1); - - Set<Resource> siblingsUnderParent0 = filterResources(parent0.getChildResources(), SIBLING_TYPE); + Resource parent2 = findResourceWithOrdinal(PARENT_TYPE, 2); + Set<Resource> testsUnderParent0 = filterResources(parent0.getChildResources(), TEST_TYPE); - Set<Resource> siblingsUnderParent1 = filterResources(parent1.getChildResources(), SIBLING_TYPE); + Set<Resource> siblingsUnderParent0 = filterResources(parent0.getChildResources(), SIBLING_TYPE); Set<Resource> testsUnderParent1 = filterResources(parent1.getChildResources(), TEST_TYPE); - + Set<Resource> siblingsUnderParent1 = filterResources(parent1.getChildResources(), SIBLING_TYPE); + Set<Resource> testsUnderParent2 = filterResources(parent2.getChildResources(), TEST_TYPE); + Set<Resource> siblingsUnderParent2 = filterResources(parent2.getChildResources(), SIBLING_TYPE); + + //first check for the successful upgrades + checkResourcesUpgraded(testsUnderParent2, 15); + checkResourcesUpgraded(siblingsUnderParent2, 15); checkResourcesUpgraded(siblingsUnderParent0, 15); checkResourcesUpgraded(testsUnderParent1, 15);
@@ -257,10 +262,72 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase }
@Test - public void testFailureOnDependencies() { - //TODO implement - //check that stuff works if there is an upgrade failure on some of the resources - //in the plugin some "in the middle" of the plugin dep graph + public void testFailureOnDependencies() throws Exception { + setCurrentServerSideInventory(new FakeServerInventory()); + + executeTestWithPlugins(getAllDepsFor(TEST_V1_PLUGIN_NAME, PARENT_SIBLING_V1_PLUGIN_NAME), + new AbstractTestPayload(true, Collections.<ResType> emptyList()) { + public void test(Map<ResType, Set<Resource>> resourceUpgradeTestResources) { + //in here we set up the failures that are going to happen when + //the v2 plugins are run + + Resource parent = findResourceWithOrdinal(PARENT_DEP_TYPE, 0); + assertNotNull(parent, "Failed to find the parent to setup the failures for."); + + addChildrenToFail(parent, PARENT_TYPE, 0); + } + + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + } + }; + } + }); + + executeTestWithPlugins(getAllDepsFor(TEST_V2_PLUGIN_NAME, PARENT_SIBLING_V2_PLUGIN_NAME), + new AbstractTestPayload(false, ALL_TYPES) { + public void test(Map<ResType, Set<Resource>> resources) { + checkPresenceOfResourceTypes(resources, getExpectedResourceTypes()); + + checkNumberOfResources(resources, ROOT_TYPE, 1); + checkNumberOfResources(resources, PARENT_DEP_TYPE, 1); + checkResourcesUpgraded(resources.get(PARENT_DEP_SIBLING_TYPE), 1); + + //check that the failed resources have the error attached to them + //we find the resource instance from the map provided to this method + //because that map contains the resources as found on the server-side + //(i.e. they include error objects). + Resource parent0 = getEqualFrom(resources.get(PARENT_TYPE), findResourceWithOrdinal(PARENT_TYPE, 0)); + Resource parent1 = getEqualFrom(resources.get(PARENT_TYPE), findResourceWithOrdinal(PARENT_TYPE, 1)); + + //v2 plugin discovers 3 resources but because parent0 failed to upgrade, + //the discovery shouldn't have occurred leaving us with the 2 already existing resources. + checkNumberOfResources(resources, PARENT_TYPE, 2); + checkResourceFailedUpgrade(parent0); + checkOthersUpgraded(resources.get(PARENT_TYPE), parent0); + + //parent1 upgraded ok, so discovering its children should have executed. + //this is v2, so we should find 15 of each. + checkResourcesUpgraded(filterResources(parent1.getChildResources(), TEST_TYPE), 15); + checkResourcesUpgraded(filterResources(parent1.getChildResources(), SIBLING_TYPE), 15); + + //these shouldn't have been upgraded. in v1 we had 10 resources of TEST_TYPE + //and 10 resources of SIBLING_TYPE and that's what we should be seeing + //now. + checkResourcesNotUpgraded(filterResources(parent0.getChildResources(), TEST_TYPE), 10); + checkResourcesNotUpgraded(filterResources(parent0.getChildResources(), SIBLING_TYPE), 10); + } + + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + } + }; + } + }); }
@SuppressWarnings("unchecked") @@ -317,6 +384,22 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase } }
+ private static void checkResourcesNotUpgraded(Set<Resource> resources, int expectedSize) { + assertEquals(resources.size(), expectedSize, "The set of resources has unexpected size."); + for(Resource res : resources) { + assertFalse(res.getResourceKey().startsWith(UPGRADED_RESOURCE_KEY_PREFIX), "Resource " + res + + " seems to be upgraded even though it shouldn't."); + + ResourceContainer rc = PluginContainer.getInstance().getInventoryManager().getResourceContainer(res); + + assertEquals(rc.getResourceComponentState(), ResourceComponentState.STOPPED, + "A resource that has not been upgraded due to upgrade error in parent should be stopped."); + + //recurse, since the whole subtree under the failed resource should be not upgraded and stopped. + checkResourcesNotUpgraded(res.getChildResources(), res.getChildResources().size()); + } + } + private static void checkResourceFailedUpgrade(Resource resource) { assertFalse(resource.getResourceKey().startsWith(UPGRADED_RESOURCE_KEY_PREFIX), "Resource " + resource + " seems to be upgraded even though it shouldn't."); diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml index 3d709b0..0f6671b 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml @@ -21,7 +21,7 @@ </runs-inside>
<plugin-configuration> - <c:simple-property name="count" default="2" /> + <c:simple-property name="count" default="3" /> <c:simple-property name="key" default="UPGRADED-test-resource-parent-%n,parent-%p" /> </plugin-configuration>
commit 9533fc2898f18af7262f513049d7261516787f4f Author: Lukas Krejci lkrejci@redhat.com Date: Mon Oct 4 14:50:49 2010 +0200
Upgrade even the non-commited resources to prevent duplication of resources in the auto-discovery queue
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index c6f1169..99a0513 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -2650,11 +2650,6 @@ public class InventoryManager extends AgentService implements ContainerService, }
private void upgradeResource(Resource resource) { - //only process committed resources - if (resource.getInventoryStatus() != InventoryStatus.COMMITTED) { - return; - } - ResourceContainer container = getResourceContainer(resource); if (container != null) { if (container.getResourceComponentState() == ResourceComponentState.STARTED) { @@ -2668,8 +2663,17 @@ public class InventoryManager extends AgentService implements ContainerService, upgradeResource(child); } } else { - log.error("The resource container for resource [" + resource - + "] wasn't started during upgrade. This should not happen."); + String message = "The resource container for resource [" + resource + + "] wasn't started while upgrading."; + + if (resource.getChildResources().isEmpty()) { + log.info(message + + " If this is the first time the plugin container starts up and has completely empty inventory, you can ignore this message."); + } else { + log.error(message + + " This can potentially cause the discovery to find resources logically equivalent to already " + + "existing resources if the corresponding plugins support upgrade for that particular resource type."); + } } } else { log.error("Resource container not initialized for resource [" + resource diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java index 39597ee..0dd3459 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java @@ -80,8 +80,6 @@ public class FakeServerInventory { this.failing = failing; }
- //need to synchronize, because resource upgrade is async and can overlap with - //resource discovery. public synchronized CustomAction mergeInventoryReport(final InventoryStatus requiredInventoryStatus) { return new CustomAction("updateServerSideInventory") { public Object invoke(Invocation invocation) throws Throwable { diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index 04858c6..8b966c3 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -71,7 +71,7 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { }
@Test - public void testIgnoreUncommittedResources() throws Exception { + public void testIncludeUncommittedResources() throws Exception { setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.NEW);
@@ -82,11 +82,12 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase {
Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next();
- assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); - assertEquals(discoveredResource.getName(), "resource-name-v1"); - assertEquals(discoveredResource.getDescription(), "resource-description-v1"); + assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); + assertEquals(discoveredResource.getName(), "resource-name-v2"); + assertEquals(discoveredResource.getDescription(), "resource-description-v2"); }
+ @SuppressWarnings("unchecked") public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { @@ -95,6 +96,9 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED)); + + oneOf(getCurrentDiscoveryServerService()).upgradeResources(with(any(Set.class))); + will(getCurrentServerSideInventory().upgradeResources()); } }; }
commit 8ecbe7dec08b0e2e1f86ad8e1e56efd9f651cc7e Author: Lukas Krejci lkrejci@redhat.com Date: Mon Oct 4 14:32:55 2010 +0200
code formatting
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index de52cd8..c6f1169 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -242,16 +242,19 @@ public class InventoryManager extends AgentService implements ContainerService, // inside EmbJopr). if (configuration.isInsideAgent()) { // After an initial delay (5s by default), periodically run an availability check (every 1m by default). - availabilityThreadPoolExecutor.scheduleWithFixedDelay(availabilityExecutor, configuration - .getAvailabilityScanInitialDelay(), configuration.getAvailabilityScanPeriod(), TimeUnit.SECONDS); + availabilityThreadPoolExecutor.scheduleWithFixedDelay(availabilityExecutor, + configuration.getAvailabilityScanInitialDelay(), configuration.getAvailabilityScanPeriod(), + TimeUnit.SECONDS);
// After an initial delay (10s by default), periodically run a server discovery scan (every 15m by default). - inventoryThreadPoolExecutor.scheduleWithFixedDelay(serverScanExecutor, configuration - .getServerDiscoveryInitialDelay(), configuration.getServerDiscoveryPeriod(), TimeUnit.SECONDS); + inventoryThreadPoolExecutor.scheduleWithFixedDelay(serverScanExecutor, + configuration.getServerDiscoveryInitialDelay(), configuration.getServerDiscoveryPeriod(), + TimeUnit.SECONDS);
// After an initial delay (20s by default), periodically run a service discovery scan (every 1d by default). - inventoryThreadPoolExecutor.scheduleWithFixedDelay(serviceScanExecutor, configuration - .getServiceDiscoveryInitialDelay(), configuration.getServiceDiscoveryPeriod(), TimeUnit.SECONDS); + inventoryThreadPoolExecutor.scheduleWithFixedDelay(serviceScanExecutor, + configuration.getServiceDiscoveryInitialDelay(), configuration.getServiceDiscoveryPeriod(), + TimeUnit.SECONDS); } } finally { inventoryLock.writeLock().unlock(); @@ -288,22 +291,23 @@ public class InventoryManager extends AgentService implements ContainerService, * * @throws Exception if the discovery component threw an exception */ - public Set<DiscoveredResourceDetails> invokeDiscoveryComponent(ResourceContainer parentResourceContainer, ResourceDiscoveryComponent component, - ResourceDiscoveryContext context) throws Exception { + public Set<DiscoveredResourceDetails> invokeDiscoveryComponent(ResourceContainer parentResourceContainer, + ResourceDiscoveryComponent component, ResourceDiscoveryContext context) throws Exception {
Resource parentResource = parentResourceContainer == null ? null : parentResourceContainer.getResource(); - + if (resourceUpgradeDelegate.hasUpgradeFailedInChildren(parentResource, context.getResourceType())) { - log.debug("Discovery of [" + context.getResourceType() + "] has been disallowed under " + (parentResource == null ? " the platform " : parentResource) + - " because some of its siblings failed to upgrade."); + log.debug("Discovery of [" + context.getResourceType() + "] has been disallowed under " + + (parentResource == null ? " the platform " : parentResource) + + " because some of its siblings failed to upgrade."); return null; } - + long timeout = getDiscoveryComponentTimeout(context.getResourceType());
try { - ResourceDiscoveryComponent proxy = this.discoveryComponentProxyFactory.getDiscoveryComponentProxy(context - .getResourceType(), component, timeout); + ResourceDiscoveryComponent proxy = this.discoveryComponentProxyFactory.getDiscoveryComponentProxy( + context.getResourceType(), component, timeout); Set<DiscoveredResourceDetails> results = proxy.discoverResources(context); return results; } catch (TimeoutException te) { @@ -335,8 +339,8 @@ public class InventoryManager extends AgentService implements ContainerService, long timeout = getDiscoveryComponentTimeout(context.getResourceType());
try { - ManualAddFacet proxy = this.discoveryComponentProxyFactory.getDiscoveryComponentProxy(context - .getResourceType(), component, timeout, ManualAddFacet.class); + ManualAddFacet proxy = this.discoveryComponentProxyFactory.getDiscoveryComponentProxy( + context.getResourceType(), component, timeout, ManualAddFacet.class); DiscoveredResourceDetails result = proxy.discoverResource(pluginConfig, context); return result; } catch (TimeoutException te) { @@ -375,8 +379,8 @@ public class InventoryManager extends AgentService implements ContainerService, component, timeout, ClassLoaderFacet.class);
ResourceDiscoveryContext discoveryContext = new ResourceDiscoveryContext(resourceType, parentComponent, - parentResourceContext, SystemInfoFactory.createSystemInfo(), null, null, this.configuration - .getContainerName(), this.configuration.getPluginContainerDeployment()); + parentResourceContext, SystemInfoFactory.createSystemInfo(), null, null, + this.configuration.getContainerName(), this.configuration.getPluginContainerDeployment());
// Configurations are not immutable, so clone the plugin config, so the plugin will not be able to change the // actual PC-managed plugin config. @@ -384,8 +388,7 @@ public class InventoryManager extends AgentService implements ContainerService, // TODO (ips): Clone the ResourceType too for the same reason.
DiscoveredResourceDetails details = new DiscoveredResourceDetails(resourceType, resource.getResourceKey(), - resource.getName(), resource.getVersion(), resource.getDescription(), pluginConfigClone, - null); // TODO: I have a feeling we'll need process info, how to get it?? + resource.getName(), resource.getVersion(), resource.getDescription(), pluginConfigClone, null); // TODO: I have a feeling we'll need process info, how to get it??
List<URL> results = proxy.getAdditionalClasspathUrls(discoveryContext, details);
@@ -592,7 +595,8 @@ public class InventoryManager extends AgentService implements ContainerService,
@NotNull // TODO (ips): Perhaps refactor this so that it shares code with AvailablityExecutor.checkInventory(). - public Availability getCurrentAvailability(Resource resource) { + public + Availability getCurrentAvailability(Resource resource) { AvailabilityType availType = null; // i.e. UNKNOWN; ResourceContainer resourceContainer = getResourceContainer(resource); if (resourceContainer != null) { @@ -665,8 +669,8 @@ public class InventoryManager extends AgentService implements ContainerService, ResourceDiscoveryContext<ResourceComponent> discoveryContext = new ResourceDiscoveryContext<ResourceComponent>( resourceType, parentResourceComponent, parentResourceContainer.getResourceContext(), SystemInfoFactory.createSystemInfo(), new ArrayList<ProcessScanResult>(0), - new ArrayList<Configuration>(0), this.configuration.getContainerName(), this.configuration - .getPluginContainerDeployment()); + new ArrayList<Configuration>(0), this.configuration.getContainerName(), + this.configuration.getPluginContainerDeployment());
// Ask the plugin's discovery component to find the new resource, throwing exceptions if it cannot be // found at all. @@ -695,8 +699,8 @@ public class InventoryManager extends AgentService implements ContainerService,
// Ask the plugin's discovery component to find the new resource, throwing exceptions if it cannot be // found at all. - Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentResourceContainer, discoveryComponent, - discoveryContext); + Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentResourceContainer, + discoveryComponent, discoveryContext); if ((discoveredResources == null) || discoveredResources.isEmpty()) { log.info("Plugin Error: During manual add, discovery component method [" + discoveryComponent.getClass().getName() + ".discoverResources()] returned " @@ -850,8 +854,7 @@ public class InventoryManager extends AgentService implements ContainerService, if ((this.platform != null) && (this.platform.getInventoryStatus() == InventoryStatus.NEW) && newPlatformWasDeletedRecently) { // let's make sure we are registered; its probable that our platform was deleted and we need to re-register - log - .info("No committed resources to send in our availability report - the platform/agent was deleted, let's re-register again"); + log.info("No committed resources to send in our availability report - the platform/agent was deleted, let's re-register again"); registerWithServer(); newPlatformWasDeletedRecently = false; // we've tried to recover from our platform being deleted, let's not do it again } @@ -891,8 +894,8 @@ public class InventoryManager extends AgentService implements ContainerService, log.debug("Availability report content: " + report.toString(log.isTraceEnabled())); }
- boolean ok = configuration.getServerServices().getDiscoveryServerService().mergeAvailabilityReport( - report); + boolean ok = configuration.getServerServices().getDiscoveryServerService() + .mergeAvailabilityReport(report); if (!ok) { // I guess I could immediately call executeAvailabilityScanImmediately and pass its results to // mergeAvailabilityReport again right now, but what happens if we've queued up a bunch of @@ -955,8 +958,7 @@ public class InventoryManager extends AgentService implements ContainerService, if ((this.platform != null) && (this.platform.getInventoryStatus() == InventoryStatus.NEW) && newPlatformWasDeletedRecently) { // let's make sure we are registered; its probable that our platform was deleted and we need to re-register - log - .info("The inventory report was invalid probably because the platform/Agent was deleted; let's re-register..."); + log.info("The inventory report was invalid probably because the platform/Agent was deleted; let's re-register..."); registerWithServer(); newPlatformWasDeletedRecently = false; // we've tried to recover from our platform being deleted, let's not do it again } @@ -974,8 +976,8 @@ public class InventoryManager extends AgentService implements ContainerService, if (syncInfo != null) { synchInventory(syncInfo); } else { - purgeObsoleteResources(Collections.<String>emptySet()); - + purgeObsoleteResources(Collections.<String> emptySet()); + //can't live without a platform, but we just deleted it. Let's rediscover it. discoverPlatform(); } @@ -1113,7 +1115,7 @@ public class InventoryManager extends AgentService implements ContainerService, return; } boolean scan = removeResourceAndIndicateIfScanIsNeeded(resourceContainer.getResource()); - + //only actually schedule the scanning when we are finished with resource upgrade. The resource upgrade //happens before any scanning infrastructure is established. if (!resourceUpgradeDelegate.enabled() && scan) { @@ -1152,8 +1154,8 @@ public class InventoryManager extends AgentService implements ContainerService, parent.removeChildResource(resource); }
- PluginContainer.getInstance().getMeasurementManager().unscheduleCollection( - Collections.singleton(resource.getId())); + PluginContainer.getInstance().getMeasurementManager() + .unscheduleCollection(Collections.singleton(resource.getId()));
if (this.resourceContainers.remove(resource.getUuid()) == null) { if (log.isDebugEnabled()) { @@ -1258,8 +1260,8 @@ public class InventoryManager extends AgentService implements ContainerService, logMessage.append("description, "); }
- logMessage.replace(logMessage.length() - 1, logMessage.length(), "to become [").append( - existingResource.toString()).append("]"); + logMessage.replace(logMessage.length() - 1, logMessage.length(), "to become [") + .append(existingResource.toString()).append("]");
log.info(logMessage.toString()); } else { @@ -1429,7 +1431,7 @@ public class InventoryManager extends AgentService implements ContainerService, } return; } - + ResourceComponent component = container.getResourceComponent();
// if the component already exists and is started, and the resource's plugin config has not changed, there is @@ -1490,8 +1492,8 @@ public class InventoryManager extends AgentService implements ContainerService, log.warn("Cannot give activated resource its discovery component. Cause: " + e); }
- ConfigurationUtility.normalizeConfiguration(resource.getPluginConfiguration(), type - .getPluginConfigurationDefinition()); + ConfigurationUtility.normalizeConfiguration(resource.getPluginConfiguration(), + type.getPluginConfigurationDefinition());
ResourceComponent parentComponent = null; if (resource.getParentResource() != null) { @@ -1855,8 +1857,7 @@ public class InventoryManager extends AgentService implements ContainerService, } } else { // This is very strange - there are no platform types - we should never be missing the built-in platform plugin. - log - .error("Missing platform plugin(s) - falling back to dummy platform impl; this should only occur in tests!"); + log.error("Missing platform plugin(s) - falling back to dummy platform impl; this should only occur in tests!"); // TODO: Set sysprop (e.g. rhq.test.mode=true) in integration tests, // and throw a runtime exception here if that sysprop is not set. return getTestPlatform(); @@ -2049,7 +2050,7 @@ public class InventoryManager extends AgentService implements ContainerService, public boolean hasUpgradeMergeFailed() { return resourceUpgradeDelegate.hasUpgradeMergeFailed(); } - + /** * Always use this before accessing the event listeners because this ensures * thread safety. @@ -2176,9 +2177,10 @@ public class InventoryManager extends AgentService implements ContainerService, try { ResourceDiscoveryContext context = new ResourceDiscoveryContext(resourceType, parentComponent, parentResourceContext, SystemInfoFactory.createSystemInfo(), processScanResults, - Collections.EMPTY_LIST, this.configuration.getContainerName(), this.configuration - .getPluginContainerDeployment()); - Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentContainer, discoveryComponent, context); + Collections.EMPTY_LIST, this.configuration.getContainerName(), + this.configuration.getPluginContainerDeployment()); + Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentContainer, + discoveryComponent, context); newResources = new HashSet<Resource>(); if ((discoveredResources != null) && (!discoveredResources.isEmpty())) { IdentityHashMap<Configuration, DiscoveredResourceDetails> pluginConfigObjects = new IdentityHashMap<Configuration, DiscoveredResourceDetails>(); @@ -2403,8 +2405,8 @@ public class InventoryManager extends AgentService implements ContainerService, if (log.isDebugEnabled()) { log.debug("Merging [" + modifiedResourceIds.size() + "] modified Resources into local inventory..."); } - Set<Resource> modifiedResources = configuration.getServerServices().getDiscoveryServerService().getResources( - modifiedResourceIds, false); + Set<Resource> modifiedResources = configuration.getServerServices().getDiscoveryServerService() + .getResources(modifiedResourceIds, false); syncSchedules(modifiedResources); // RHQ-792, mtime is the indicator that schedules should be sync'ed too for (Resource modifiedResource : modifiedResources) { mergeResource(modifiedResource); @@ -2620,12 +2622,12 @@ public class InventoryManager extends AgentService implements ContainerService,
private void upgradeResources() { try { - + if (!configuration.isInsideAgent()) { log.debug("Skipping resource upgrade in embedded mode."); return; } - + log.debug("Executing resource upgrade.");
boolean syncResult = handleReport(new InventoryReport(getAgent()), true); @@ -2635,7 +2637,7 @@ public class InventoryManager extends AgentService implements ContainerService, }
upgradeResource(getPlatform()); - + log.debug("Sending the upgrade requests to the server."); resourceUpgradeDelegate.sendRequests();
commit 9050f4bfab5114ff31e19cb9c04b2d087dba2bff Author: Lukas Krejci lkrejci@redhat.com Date: Mon Oct 4 14:04:52 2010 +0200
Adding the test for handling the failure to upgrade some of the resources on the leaf of the plugin dependency graph.
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ForwardingProxy.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ForwardingProxy.java new file mode 100644 index 0000000..7c7d277 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ForwardingProxy.java @@ -0,0 +1,72 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +/** + * This class provides a simple proxy that just forwards the calls to the + * actual object. + * <p> + * This seemingly pointless behavior is useful when dealing with the classes + * loaded in different classloaders. + * <p> + * The arguments passed to the method invocations of the proxy must unfortunately be "understandable" + * both in the "current" classloader and in the context of the classloader that loaded the target object. + * I don't know about a generic solution to this problem. + * A partial solution would be to serialize the arguments and deserialize them in the context + * of the target classloader but that doesn't cut it for non-serializable classes obviously. + * + * @author Lukas Krejci + */ +public class ForwardingProxy { + + private static class ForwardingHandler implements InvocationHandler { + private Object target; + + public ForwardingHandler(Object target) { + this.target = target; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Method targetMethod = findMethodOnTarget(method); + + return targetMethod.invoke(target, args); + } + + private Method findMethodOnTarget(Method method) throws SecurityException, NoSuchMethodException { + Class<?>[] origParamTypes = method.getParameterTypes(); + + return target.getClass().getMethod(method.getName(), origParamTypes); + } + } + + public static <T> T forward(Object target, Class<T> targetInterface, Class<?>... additionalInterfaces) { + Class<?>[] interfaces = new Class<?>[additionalInterfaces.length + 1]; + interfaces[0] = targetInterface; + System.arraycopy(additionalInterfaces, 0, interfaces, 1, additionalInterfaces.length); + + Object proxy = Proxy.newProxyInstance(targetInterface.getClassLoader(), interfaces, new ForwardingHandler(target)); + return targetInterface.cast(proxy); + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java index 5949b76..7eafafc 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java @@ -20,14 +20,17 @@ package org.rhq.core.pc.upgrade;
import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail;
import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -36,10 +39,20 @@ import org.jmock.Expectations; import org.jmock.Mockery; import org.testng.annotations.Test;
+import org.rhq.core.clientapi.agent.PluginContainerException; +import org.rhq.core.clientapi.agent.discovery.InvalidPluginConfigurationClientException; import org.rhq.core.clientapi.server.discovery.InvalidInventoryReportException; import org.rhq.core.clientapi.server.discovery.InventoryReport; +import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceErrorType; +import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.pc.PluginContainer; +import org.rhq.core.pc.inventory.InventoryManager; +import org.rhq.core.pc.inventory.ResourceContainer; +import org.rhq.core.pc.inventory.ResourceContainer.ResourceComponentState; +import org.rhq.core.pc.upgrade.plugins.multi.base.BaseResourceComponentInterface; import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet;
/** @@ -76,7 +89,7 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase private static final String TEST_V2_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-test-2.0.0.jar";
private static final String UPGRADED_RESOURCE_KEY_PREFIX = "UPGRADED"; - + private static final HashMap<String, List<String>> DEPS;
static { @@ -100,9 +113,12 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase private static final ResType SIBLING_TYPE = new ResType("TestResourceSibling", "test"); private static final ResType PARENT_TYPE = new ResType("TestResourceParent", "test"); private static final ResType PARENT_DEP_TYPE = new ResType("ParentDependency", "parentdep"); - private static final ResType PARENT_SIBLING_TYPE = new ResType("ParentDepSibling", "parentsibling"); + private static final ResType PARENT_DEP_SIBLING_TYPE = new ResType("ParentDepSibling", "parentsibling"); private static final ResType ROOT_TYPE = new ResType("Root", "root");
+ private static List<ResType> ALL_TYPES = Arrays.asList(TEST_TYPE, SIBLING_TYPE, PARENT_TYPE, PARENT_DEP_TYPE, + PARENT_DEP_SIBLING_TYPE, ROOT_TYPE); + protected Collection<String> getRequiredPlugins() { return Arrays.asList(BASE_PLUGIN_NAME, PARENT_DEP_V1_PLUGIN_NAME, PARENT_DEP_V2_PLUGIN_NAME, PARENT_SIBLING_V1_PLUGIN_NAME, PARENT_SIBLING_V2_PLUGIN_NAME, ROOT_PLUGIN_NAME, SIBLING_V1_PLUGIN_NAME, @@ -129,26 +145,20 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase });
//now let's run with v2 plugins and check the layout of the inventory - executeTestWithPlugins( - getAllDepsFor(TEST_V2_PLUGIN_NAME, PARENT_SIBLING_V2_PLUGIN_NAME), - new AbstractTestPayload(false, Arrays.asList(TEST_TYPE, SIBLING_TYPE, PARENT_TYPE, PARENT_DEP_TYPE, - PARENT_SIBLING_TYPE, ROOT_TYPE)) { + executeTestWithPlugins(getAllDepsFor(TEST_V2_PLUGIN_NAME, PARENT_SIBLING_V2_PLUGIN_NAME), + new AbstractTestPayload(false, ALL_TYPES) {
public void test(Map<ResType, Set<Resource>> resources) { checkPresenceOfResourceTypes(resources, getExpectedResourceTypes());
checkNumberOfResources(resources, ROOT_TYPE, 1); checkNumberOfResources(resources, PARENT_DEP_TYPE, 1); - checkNumberOfResources(resources, PARENT_SIBLING_TYPE, 1); - checkNumberOfResources(resources, PARENT_TYPE, 2); - checkNumberOfResources(resources, SIBLING_TYPE, 30); - checkNumberOfResources(resources, TEST_TYPE, 30); - + //check that the resources are upgraded - checkResourcesUpgraded(resources.get(PARENT_SIBLING_TYPE)); - checkResourcesUpgraded(resources.get(PARENT_TYPE)); - checkResourcesUpgraded(resources.get(SIBLING_TYPE)); - checkResourcesUpgraded(resources.get(TEST_TYPE)); + checkResourcesUpgraded(resources.get(PARENT_DEP_SIBLING_TYPE), 1); + checkResourcesUpgraded(resources.get(PARENT_TYPE), 2); + checkResourcesUpgraded(resources.get(SIBLING_TYPE), 30); + checkResourcesUpgraded(resources.get(TEST_TYPE), 30); }
public Expectations getExpectations(Mockery context) throws Exception { @@ -162,10 +172,88 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase }
@Test - public void testFailureOnLeaf() { - //TODO implement - //check that the system behaves correctly if there is an upgrade failure - //at the leaf node of the plugin dep graph + public void testFailureOnLeaf() throws Exception { + setCurrentServerSideInventory(new FakeServerInventory()); + + executeTestWithPlugins(getAllDepsFor(TEST_V1_PLUGIN_NAME, PARENT_SIBLING_V1_PLUGIN_NAME), + new AbstractTestPayload(true, Collections.<ResType> emptyList()) { + public void test(Map<ResType, Set<Resource>> resourceUpgradeTestResources) { + //in here we set up the failures that are going to happen when + //the v2 plugins are run + + Resource parent0 = findResourceWithOrdinal(PARENT_TYPE, 0); + assertNotNull(parent0, "Failed to find the parent to setup the failures for."); + Resource parent1 = findResourceWithOrdinal(PARENT_TYPE, 1); + assertNotNull(parent1, "Failed to find the parent to setup the failures for."); + + addChildrenToFail(parent0, TEST_TYPE, 1, 2); + addChildrenToFail(parent1, SIBLING_TYPE, 1); + } + + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + } + }; + } + }); + + executeTestWithPlugins(getAllDepsFor(TEST_V2_PLUGIN_NAME, PARENT_SIBLING_V2_PLUGIN_NAME), + new AbstractTestPayload(false, ALL_TYPES) { + public void test(Map<ResType, Set<Resource>> resources) { + checkPresenceOfResourceTypes(resources, getExpectedResourceTypes()); + + checkNumberOfResources(resources, ROOT_TYPE, 1); + checkNumberOfResources(resources, PARENT_DEP_TYPE, 1); + checkNumberOfResources(resources, PARENT_TYPE, 2); + + checkResourcesUpgraded(resources.get(PARENT_TYPE), 2); + checkResourcesUpgraded(resources.get(PARENT_DEP_SIBLING_TYPE), 1); + + Resource parent0 = findResourceWithOrdinal(PARENT_TYPE, 0); + Resource parent1 = findResourceWithOrdinal(PARENT_TYPE, 1); + + Set<Resource> siblingsUnderParent0 = filterResources(parent0.getChildResources(), SIBLING_TYPE); + Set<Resource> testsUnderParent0 = filterResources(parent0.getChildResources(), TEST_TYPE); + Set<Resource> siblingsUnderParent1 = filterResources(parent1.getChildResources(), SIBLING_TYPE); + Set<Resource> testsUnderParent1 = filterResources(parent1.getChildResources(), TEST_TYPE); + + checkResourcesUpgraded(siblingsUnderParent0, 15); + checkResourcesUpgraded(testsUnderParent1, 15); + + //there should be no newly discovered sibling resources of the failed ones + assertEquals(testsUnderParent0.size(), 10); + assertEquals(siblingsUnderParent1.size(), 10); + + //check that the failed resources have the error attached to them + //we find the resource instance from the map provided to this method + //because that map contains the resources as found on the server-side + //(i.e. they include error objects). + Resource failedTest1 = getEqualFrom(resources.get(TEST_TYPE), + findResourceWithOrdinal(testsUnderParent0, 1)); + Resource failedTest2 = getEqualFrom(resources.get(TEST_TYPE), + findResourceWithOrdinal(testsUnderParent0, 2)); + + checkResourceFailedUpgrade(failedTest1); + checkResourceFailedUpgrade(failedTest2); + checkOthersUpgraded(testsUnderParent0, failedTest1, failedTest2); + + Resource failedSibling = getEqualFrom(resources.get(SIBLING_TYPE), + findResourceWithOrdinal(siblingsUnderParent1, 1)); + + checkResourceFailedUpgrade(failedSibling); + checkOthersUpgraded(siblingsUnderParent1, failedSibling); + } + + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + } + }; + } + }); }
@Test @@ -180,13 +268,14 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase protected void defineDefaultExpectations(Expectations expectations) { super.defineDefaultExpectations(expectations); try { - expectations.allowing(getCurrentDiscoveryServerService()) - .mergeInventoryReport(expectations.with(Expectations.any(InventoryReport.class))); + expectations.allowing(getCurrentDiscoveryServerService()).mergeInventoryReport( + expectations.with(Expectations.any(InventoryReport.class))); expectations.will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
- expectations.allowing(getCurrentDiscoveryServerService()).upgradeResources(expectations.with(Expectations.any(Set.class))); + expectations.allowing(getCurrentDiscoveryServerService()).upgradeResources( + expectations.with(Expectations.any(Set.class))); expectations.will(getCurrentServerSideInventory().upgradeResources()); - + expectations.allowing(getCurrentDiscoveryServerService()).postProcessNewlyCommittedResources( expectations.with(Expectations.any(Set.class)));
@@ -214,10 +303,112 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase private static void checkNumberOfResources(Map<ResType, Set<Resource>> resources, ResType type, int count) { assertEquals(resources.get(type).size(), count, "Unexpected number of " + type + " discovered."); } - - private static void checkResourcesUpgraded(Set<Resource> resources) { - for(Resource res : resources) { - assertTrue(res.getResourceKey().startsWith(UPGRADED_RESOURCE_KEY_PREFIX), "Resource " + res + " doesn't seem to be upgraded even though it should."); + + private static void checkResourcesUpgraded(Set<Resource> resources, int expectedSize) { + assertEquals(resources.size(), expectedSize, "The set of resources has unexpected size."); + for (Resource res : resources) { + assertTrue(res.getResourceKey().startsWith(UPGRADED_RESOURCE_KEY_PREFIX), "Resource " + res + + " doesn't seem to be upgraded even though it should."); + + ResourceContainer rc = PluginContainer.getInstance().getInventoryManager().getResourceContainer(res); + + assertEquals(rc.getResourceComponentState(), ResourceComponentState.STARTED, + "A resource that successfully upgraded should be started."); + } + } + + private static void checkResourceFailedUpgrade(Resource resource) { + assertFalse(resource.getResourceKey().startsWith(UPGRADED_RESOURCE_KEY_PREFIX), "Resource " + resource + + " seems to be upgraded even though it shouldn't."); + assertTrue(resource.getResourceErrors(ResourceErrorType.UPGRADE).size() == 1, + "The failed resource should have an error associated with it."); + + ResourceContainer rc = PluginContainer.getInstance().getInventoryManager().getResourceContainer(resource); + + assertEquals(rc.getResourceComponentState(), ResourceComponentState.STOPPED, + "A resource that failed to upgrade should be stopped."); + } + + private static void checkOthersUpgraded(Set<Resource> resources, Resource... failedResource) { + Set<Resource> others = new HashSet<Resource>(resources); + others.removeAll(Arrays.asList(failedResource)); + checkResourcesUpgraded(others, others.size()); + } + + private void addChildrenToFail(Resource parent, ResType childResType, int... childrenOrdinals) { + InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager(); + ResourceContainer parentContainer = inventoryManager.getResourceContainer(parent); + BaseResourceComponentInterface parentComponent = (BaseResourceComponentInterface) parentContainer + .getResourceComponent(); + + Map<String, Set<Integer>> childrenToFail = new HashMap<String, Set<Integer>>(); + Set<Integer> ordinals = new HashSet<Integer>(); + for (int i = 0; i < childrenOrdinals.length; ++i) { + ordinals.add(childrenOrdinals[i]); + } + + childrenToFail.put(childResType.getResourceTypeName(), ordinals); + + Configuration newPluginConfig = parentComponent.createPluginConfigurationWithMarkedFailures(childrenToFail); + + try { + int resourceId = parent.getId(); + inventoryManager.updatePluginConfiguration(resourceId, newPluginConfig); + } catch (InvalidPluginConfigurationClientException e) { + fail("Updating plugin configuration failed.", e); + } catch (PluginContainerException e) { + fail("Updating plugin configuration failed.", e); + } + } + + private Resource findResourceWithOrdinal(ResType resType, int ordinal) { + ResourceType resourceType = PluginContainer.getInstance().getPluginManager().getMetadataManager() + .getType(resType.getResourceTypeName(), resType.getResourceTypePluginName()); + + InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager(); + Set<Resource> resources = inventoryManager.getResourcesWithType(resourceType); + + return findResourceWithOrdinal(resources, ordinal); + } + + private Resource findResourceWithOrdinal(Set<Resource> resources, int ordinal) { + for (Resource r : resources) { + Configuration pluginConfig = r.getPluginConfiguration(); + String ordinalString = pluginConfig.getSimpleValue("ordinal", null); + + if (ordinalString != null && Integer.parseInt(ordinalString) == ordinal) { + return r; + } + } + + return null; + } + + private Set<Resource> filterResources(Set<Resource> resources, ResType resType) { + Set<Resource> ret = new HashSet<Resource>(resources); + + Iterator<Resource> it = ret.iterator(); + + while (it.hasNext()) { + ResourceType resourceType = it.next().getResourceType(); + + if (!resourceType.getName().equals(resType.getResourceTypeName()) + || !resourceType.getPlugin().equals(resType.getResourceTypePluginName())) { + + it.remove(); + } } + + return ret; + } + + private static <T> T getEqualFrom(Collection<? extends T> collection, T object) { + for (T other : collection) { + if (object.equals(other)) { + return other; + } + } + + return null; } } diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index d47d00c..04858c6 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -37,12 +37,13 @@ import java.util.Set;
import org.jmock.Expectations; import org.jmock.Mockery; +import org.testng.annotations.Test; + import org.rhq.core.clientapi.server.discovery.InventoryReport; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; import org.rhq.core.pc.PluginContainer; import org.rhq.core.pc.inventory.ResourceContainer; -import org.testng.annotations.Test;
/** * Test cases for resource upgrade. @@ -55,234 +56,255 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { private static final String PLUGIN_V1_FILENAME = "/resource-upgrade-test-plugin-1.0.0.jar"; private static final String PLUGIN_V2_FILENAME = "/resource-upgrade-test-plugin-2.0.0.jar"; private static final String FAILING_PLUGIN_FILE_NAME = "/resource-upgrade-test-plugin-3.0.0.jar"; - + private static final String SINGLETON_RESOURCE_TYPE_NAME = "Resource"; private static final String SINGLETON_RESOURCE_TYPE_PLUGIN_NAME = "ResourceUpgradeTest"; - private static final ResType SINGLETON_TYPE = new ResType(SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME); - + private static final ResType SINGLETON_TYPE = new ResType(SINGLETON_RESOURCE_TYPE_NAME, + SINGLETON_RESOURCE_TYPE_PLUGIN_NAME); + private static List<ResType> getMyExpectedTypes() { return Arrays.asList(SINGLETON_TYPE); } - + protected Collection<String> getRequiredPlugins() { return Arrays.asList(PLUGIN_V1_FILENAME, PLUGIN_V2_FILENAME, FAILING_PLUGIN_FILE_NAME); } - + @Test public void testIgnoreUncommittedResources() throws Exception { setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.NEW); - - TestPayload testNoChange = new AbstractTestPayload(false, getMyExpectedTypes()) { + + TestPayload testNoChange = new AbstractTestPayload(false, getMyExpectedTypes()) { public void test(Map<ResType, Set<Resource>> discoveredResources) { - assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); - + assertEquals(discoveredResources.get(SINGLETON_TYPE).size(), 1, + "Expected single test resource but multiple found."); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next();
assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); assertEquals(discoveredResource.getName(), "resource-name-v1"); assertEquals(discoveredResource.getDescription(), "resource-description-v1"); } - + public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { defineDefaultExpectations(this); - - between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED)); } }; } }; - + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), testNoChange); } - + @Test public void testUpgradeData() throws Exception { setCurrentServerSideInventory(new FakeServerInventory()); upgradeTest(false); } - + @Test public void testInventoryReinitializationFromServerDuringUpgrade() throws Exception { setCurrentServerSideInventory(new FakeServerInventory()); upgradeTest(true); } - + @Test public void testSkipUpgradeWhenServerUnavailable() throws Exception { setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.COMMITTED); - + getCurrentServerSideInventory().setFailing(true);
- TestPayload test = new AbstractTestPayload(false, getMyExpectedTypes()) { + TestPayload test = new AbstractTestPayload(false, getMyExpectedTypes()) { public void test(Map<ResType, Set<Resource>> discoveredResources) { - assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); - + assertEquals(discoveredResources.get(SINGLETON_TYPE).size(), 1, + "Expected single test resource but multiple found."); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next(); - + assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); assertEquals(discoveredResource.getName(), "resource-name-v1"); assertEquals(discoveredResource.getDescription(), "resource-description-v1"); } - + @SuppressWarnings("unchecked") public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { defineDefaultExpectations(this); - - between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED)); - + never(getCurrentDiscoveryServerService()).upgradeResources(with(any(Set.class))); } }; } }; - + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), test); } - + @Test public void testUpgradeWithPlatformDeletedOnServer() throws Exception { setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.COMMITTED); - - TestPayload test = new AbstractTestPayload(false, getMyExpectedTypes()) { + + TestPayload test = new AbstractTestPayload(false, getMyExpectedTypes()) { public void test(Map<ResType, Set<Resource>> discoveredResources) { - assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); - + assertEquals(discoveredResources.get(SINGLETON_TYPE).size(), 1, + "Expected single test resource but multiple found."); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next(); - + assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); assertEquals(discoveredResource.getName(), "resource-name-v2"); assertEquals(discoveredResource.getDescription(), "resource-description-v2");
- ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(discoveredResource); + ResourceContainer container = PluginContainer.getInstance().getInventoryManager() + .getResourceContainer(discoveredResource); File dataDir = container.getResourceContext().getDataDirectory(); - + File marker = new File(dataDir, "upgrade-succeeded"); - - assertFalse(marker.exists(), "The upgrade seems to have occured even though there shouldn't have been a resource to upgrade."); + + assertFalse(marker.exists(), + "The upgrade seems to have occured even though there shouldn't have been a resource to upgrade."); } - + @SuppressWarnings("unchecked") public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { defineDefaultExpectations(this); - + //the first merge will be triggered from within the upgrade process and we are //going to report null sync. - oneOf(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + oneOf(getCurrentDiscoveryServerService()) + .mergeInventoryReport(with(any(InventoryReport.class))); will(getCurrentServerSideInventory().clearPlatform()); - + //the rest of the inventory merges are executed by discoveries, so let's import the //discovered stuff into the server-side inventory. - between(1, 3).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + between(1, 3).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED)); - + never(getCurrentDiscoveryServerService()).upgradeResources(with(any(Set.class))); } }; } }; - + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), test); } - + @Test public void testUpgradeFailureHandling() throws Exception { setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.COMMITTED); - - TestPayload test = new AbstractTestPayload(false, getMyExpectedTypes()) { + + TestPayload test = new AbstractTestPayload(false, getMyExpectedTypes()) { public void test(Map<ResType, Set<Resource>> resourceUpgradeTestResources) { - assertEquals(resourceUpgradeTestResources.size(), 1, "Expected single test resource but multiple found."); - + assertEquals(resourceUpgradeTestResources.get(SINGLETON_TYPE).size(), 1, + "Expected single test resource but multiple found."); + Resource discoveredResource = resourceUpgradeTestResources.get(SINGLETON_TYPE).iterator().next(); - - assertTrue(discoveredResource.getResourceErrors().size() > 0, "There should be upgrade errors persisted on the server side."); - + + assertTrue(discoveredResource.getResourceErrors().size() > 0, + "There should be upgrade errors persisted on the server side."); + //the discovery of the failed resource mustn't have run - ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(discoveredResource); + ResourceContainer container = PluginContainer.getInstance().getInventoryManager() + .getResourceContainer(discoveredResource); File dataDir = container.getResourceContext().getDataDirectory(); - + File marker = new File(dataDir, "failing-discovery-ran"); - - assertFalse(marker.exists(), "The discovery of the resource type with a failed upgraded resource must not be executed but it was."); + + assertFalse(marker.exists(), + "The discovery of the resource type with a failed upgraded resource must not be executed but it was."); } - + @SuppressWarnings("unchecked") public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { defineDefaultExpectations(this); - - between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED)); - + oneOf(getCurrentDiscoveryServerService()).upgradeResources(with(any(Set.class))); will(getCurrentServerSideInventory().upgradeResources()); } }; } }; - + executeTestWithPlugins(Collections.singleton(FAILING_PLUGIN_FILE_NAME), test); } - + private void initialSyncAndDiscovery(final InventoryStatus requiredInventoryStatus) throws Exception { cleanDataDir(); - executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), new AbstractTestPayload(true, getMyExpectedTypes()) { + executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), new AbstractTestPayload(true, + getMyExpectedTypes()) { public void test(Map<ResType, Set<Resource>> discoveredResources) { - assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); - + assertEquals(discoveredResources.get(SINGLETON_TYPE).size(), 1, + "Expected single test resource but multiple found."); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next(); - + assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); assertEquals(discoveredResource.getName(), "resource-name-v1"); assertEquals(discoveredResource.getDescription(), "resource-description-v1"); } - + public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { defineDefaultExpectations(this); - - between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(requiredInventoryStatus)); } }; } - }); - + }); + }
- private void upgradeTest(boolean clearInventoryDat) throws Exception { initialSyncAndDiscovery(InventoryStatus.COMMITTED); - - executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), new AbstractTestPayload(clearInventoryDat, getMyExpectedTypes()) { + + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), new AbstractTestPayload(clearInventoryDat, + getMyExpectedTypes()) { public void test(Map<ResType, Set<Resource>> discoveredResources) { - assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); - + assertEquals(discoveredResources.get(SINGLETON_TYPE).size(), 1, + "Expected single test resource but multiple found."); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next(); - + assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); assertEquals(discoveredResource.getName(), "resource-name-v2"); assertEquals(discoveredResource.getDescription(), "resource-description-v2"); - - ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(discoveredResource); + + ResourceContainer container = PluginContainer.getInstance().getInventoryManager() + .getResourceContainer(discoveredResource); File dataDir = container.getResourceContext().getDataDirectory(); - + File marker = new File(dataDir, "upgrade-succeeded"); - - assertTrue(marker.exists(), "The upgrade success marker file wasn't found. This means the upgrade didn't actually run."); + + assertTrue(marker.exists(), + "The upgrade success marker file wasn't found. This means the upgrade didn't actually run."); }
@SuppressWarnings("unchecked") @@ -290,10 +312,11 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { return new Expectations() { { defineDefaultExpectations(this); - - between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport( + with(any(InventoryReport.class))); will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED)); - + oneOf(getCurrentDiscoveryServerService()).upgradeResources(with(any(Set.class))); will(getCurrentServerSideInventory().upgradeResources()); } diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponent.java index c5bbf3a..04d3767 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponent.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponent.java @@ -19,11 +19,18 @@
package org.rhq.core.pc.upgrade.plugins.multi.base;
-import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.rhq.core.domain.configuration.Configuration; +import org.rhq.core.domain.configuration.Property; +import org.rhq.core.domain.configuration.PropertyList; +import org.rhq.core.domain.configuration.PropertyMap; +import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; import org.rhq.core.pluginapi.inventory.ResourceComponent; @@ -33,13 +40,11 @@ import org.rhq.core.pluginapi.inventory.ResourceContext; * * @author Lukas Krejci */ -public class BaseResourceComponent<T extends ResourceComponent> implements ResourceComponent<T> { +public class BaseResourceComponent<T extends ResourceComponent> implements ResourceComponent<T>, BaseResourceComponentInterface {
private ResourceContext<T> context; private final Log log = LogFactory.getLog(getClass());
- private Set<Integer> childrenToFailUpgrade; - public AvailabilityType getAvailability() { return AvailabilityType.UP; } @@ -57,11 +62,57 @@ public class BaseResourceComponent<T extends ResourceComponent> implements Resou return context.getPluginConfiguration().getSimple("ordinal").getIntegerValue(); }
- public Set<Integer> getChildrenToFailUpgrade() { - return childrenToFailUpgrade == null ? Collections.<Integer>emptySet() : childrenToFailUpgrade; + public Map<String, Set<Integer>> getChildrenToFailUpgrade() { + + Map<String, Set<Integer>> ret = new HashMap<String, Set<Integer>>(); + + Configuration pluginConfig = context.getPluginConfiguration(); + PropertyList childrenToFail = pluginConfig.getList("childrenToFail"); + + if (childrenToFail != null) { + for(Property p : childrenToFail.getList()) { + PropertyMap entry = (PropertyMap) p; + + String type = entry.getSimpleValue("type", null); + + PropertyList typeList = entry.getList("children"); + + if (type != null && typeList != null) { + Set<Integer> ordinals = new HashSet<Integer>(); + + for(Property pp : typeList.getList()) { + ordinals.add(((PropertySimple)pp).getIntegerValue()); + } + + ret.put(type, ordinals); + } + } + } + + return ret; }
- public void setChildrenToFailUpgrade(Set<Integer> childrenToFailUpgrade) { - this.childrenToFailUpgrade = childrenToFailUpgrade; + public Configuration createPluginConfigurationWithMarkedFailures(Map<String, Set<Integer>> childrenToFailUpgrade) { + Configuration ret = context.getPluginConfiguration().clone(); + PropertyList list = new PropertyList("childrenToFail"); + + for(Map.Entry<String, Set<Integer>> entry : childrenToFailUpgrade.entrySet()) { + PropertyMap configEntry = new PropertyMap("childrenInType"); + configEntry.put(new PropertySimple("type", entry.getKey())); + + PropertyList typeList = new PropertyList("children"); + + for(Integer childOrdinal : entry.getValue()) { + typeList.add(new PropertySimple("ordinal", childOrdinal)); + } + + configEntry.put(typeList); + + list.add(configEntry); + } + + ret.put(list); + + return ret; } } diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponentInterface.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponentInterface.java new file mode 100644 index 0000000..1c9bef0 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponentInterface.java @@ -0,0 +1,36 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade.plugins.multi.base; + +import java.util.Map; +import java.util.Set; + +import org.rhq.core.domain.configuration.Configuration; + +/** + * This is to support proxying to required methods from the tests. + * + * @author Lukas Krejci + */ +public interface BaseResourceComponentInterface { + + Configuration createPluginConfigurationWithMarkedFailures(Map<String, Set<Integer>> childrenToFailUpgrade); + +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java index ec1cb20..5b8af94 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java @@ -19,6 +19,8 @@
package org.rhq.core.pc.upgrade.plugins.multi.base;
+import java.util.Set; + import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; @@ -41,7 +43,10 @@ public class BaseUpgradingDiscoveryComponent<T extends BaseResourceComponent> ex boolean fail = Boolean.getBoolean(pluginConfig.getSimpleValue("failUpgrade", "false"));
if (!fail && parent != null) { - fail = parent.getChildrenToFailUpgrade().contains(Integer.valueOf(ordinal)); + String typeName = inventoriedResource.getResourceType().getName(); + Set<Integer> failingOrdinals = parent.getChildrenToFailUpgrade().get(typeName); + + fail = failingOrdinals != null && failingOrdinals.contains(Integer.valueOf(ordinal)); }
if (fail) { diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/NothingDiscoveringDiscoveryComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/NothingDiscoveringDiscoveryComponent.java new file mode 100644 index 0000000..b6189e5 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/NothingDiscoveringDiscoveryComponent.java @@ -0,0 +1,42 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade.plugins.multi.base; + +import java.util.Collections; +import java.util.Set; + +import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails; +import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; + +/** + * + * @author Lukas Krejci + */ +public class NothingDiscoveringDiscoveryComponent<T extends ResourceComponent> implements ResourceDiscoveryComponent<T> { + + public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<T> context) + throws InvalidPluginConfigurationException, Exception { + + return Collections.emptySet(); + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml index d3ea7b7..e3b4f9b 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml @@ -11,7 +11,7 @@
<depends plugin="base" useClasses="true"/>
- <server name="Bogus" class="BaseDiscoveryComponent"> + <server name="Bogus" class="BaseDiscoveryComponent" discovery="NothingDiscoveringDiscoveryComponent"> <!-- This service is put in the type hierarchy in the v1/v2 test plugins --> <service name="TestResourceSibling" discovery="BaseDiscoveryComponent" diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml index f7f7a2c..e7792b9 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml @@ -10,7 +10,7 @@
<depends plugin="base" useClasses="true"/>
- <server name="Bogus" class="BaseDiscoveryComponent"> + <server name="Bogus" class="BaseDiscoveryComponent" discovery="NothingDiscoveringDiscoveryComponent"> <!-- This service is put in the type hierarchy in the v1/v2 test plugins --> <service name="TestResourceSibling" discovery="BaseUpgradingDiscoveryComponent"
commit e6dd8c2618a009053b06c3f63fff808fc5e64dbf Merge: 14fd25e... 3c5a00e... Author: Lukas Krejci lkrejci@redhat.com Date: Fri Oct 1 12:58:36 2010 +0200
Merge branch 'master' into resource-upgrade
commit 14fd25e86c1a4013c1047c343f3860720a3f9c68 Author: Lukas Krejci lkrejci@redhat.com Date: Fri Oct 1 12:55:37 2010 +0200
Adapted the resource upgrade test infrastructure to work with the new requirements of the failure handling tests and added the first round of the failure handling tests.
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java index adb3989..39597ee 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java @@ -59,68 +59,69 @@ public class FakeServerInventory { private Map<String, Resource> resourceStore = new HashMap<String, Resource>(); private int counter; private boolean failing; - + private static final Comparator<Resource> ID_COMPARATOR = new Comparator<Resource>() { public int compare(Resource o1, Resource o2) { return o1.getId() - o2.getId(); } }; - + private static final Comparator<Resource> RESOURCE_TYPE_COMPARATOR = new Comparator<Resource>() { public int compare(Resource o1, Resource o2) { return o1.getResourceType().equals(o2.getResourceType()) ? 0 : o1.getId() - o2.getId(); } }; - + public FakeServerInventory() { this(false); } - + public FakeServerInventory(boolean failing) { this.failing = failing; } - + //need to synchronize, because resource upgrade is async and can overlap with //resource discovery. public synchronized CustomAction mergeInventoryReport(final InventoryStatus requiredInventoryStatus) { return new CustomAction("updateServerSideInventory") { public Object invoke(Invocation invocation) throws Throwable { throwIfFailing(); - + InventoryReport inventoryReport = (InventoryReport) invocation.getParameter(0); - - for(Resource res : inventoryReport.getAddedRoots()) { + + for (Resource res : inventoryReport.getAddedRoots()) { + Resource persisted = fakePersist(res, requiredInventoryStatus, new HashSet<String>()); + if (res.getParentResource() == Resource.ROOT) { - platform = fakePersist(res, requiredInventoryStatus, new HashSet<String>()); - break; + platform = persisted; } } return getSyncInfo(); - } + } }; } - + public synchronized CustomAction clearPlatform() { return new CustomAction("updateServerSideInventory - report platform deleted on the server") { public Object invoke(Invocation invocation) throws Throwable { throwIfFailing(); - + platform = null; - + return getSyncInfo(); } }; } - + public synchronized CustomAction upgradeResources() { return new CustomAction("upgradeServerSideInventory") { - @SuppressWarnings({"serial", "unchecked"}) + @SuppressWarnings({ "serial", "unchecked" }) public Object invoke(Invocation invocation) throws Throwable { throwIfFailing(); - + Set<ResourceUpgradeRequest> requests = (Set<ResourceUpgradeRequest>) invocation.getParameter(0); Set<ResourceUpgradeResponse> responses = new HashSet<ResourceUpgradeResponse>(); - + for (final ResourceUpgradeRequest request : requests) { Resource resource = findResource(platform, new Resource() { public int getId() { @@ -134,16 +135,18 @@ public class FakeServerInventory { if (request.getNewName() != null) { resource.setName(request.getNewName()); } - + if (request.getNewResourceKey() != null) { resource.setResourceKey(request.getNewResourceKey()); } - + if (request.getUpgradeErrorMessage() != null) { - ResourceError error = new ResourceError(resource, ResourceErrorType.UPGRADE, request.getUpgradeErrorMessage(), request.getUpgradeErrorStackTrace(), request.getTimestamp()); + ResourceError error = new ResourceError(resource, ResourceErrorType.UPGRADE, + request.getUpgradeErrorMessage(), request.getUpgradeErrorStackTrace(), + request.getTimestamp()); resource.getResourceErrors().add(error); } - + ResourceUpgradeResponse resp = new ResourceUpgradeResponse(); resp.setResourceId(resource.getId()); resp.setUpgradedResourceName(resource.getName()); @@ -156,21 +159,21 @@ public class FakeServerInventory { } }; } - + public synchronized CustomAction getResources() { return new CustomAction("getResources") { @SuppressWarnings("unchecked") public Object invoke(Invocation invocation) throws Throwable { throwIfFailing(); - - Set<Integer> resourceIds = (Set<Integer>)invocation.getParameter(0); + + Set<Integer> resourceIds = (Set<Integer>) invocation.getParameter(0); boolean includeDescendants = (Boolean) invocation.getParameter(1); - + return getResources(resourceIds, includeDescendants); } - }; + }; } - + public boolean isFailing() { return failing; } @@ -191,12 +194,12 @@ public class FakeServerInventory { } return result; } - + @SuppressWarnings("serial") - private Set<Resource> getResources(Set<Integer> resourceIds, boolean includeDescendants) { + private Set<Resource> getResources(Set<Integer> resourceIds, boolean includeDescendants) { Set<Resource> result = new HashSet<Resource>(); - - for(final Integer id : resourceIds) { + + for (final Integer id : resourceIds) { Resource r = findResource(platform, new Resource() { public int getId() { return id; @@ -204,19 +207,20 @@ public class FakeServerInventory { }, ID_COMPARATOR); if (r != null) { result.add(r); - + if (includeDescendants) { - for(Resource child : r.getChildResources()) { + for (Resource child : r.getChildResources()) { result.addAll(getResources(Collections.singleton(child.getId()), true)); } } } } - + return result; } - - private Resource fakePersist(Resource agentSideResource, InventoryStatus requiredInventoryStatus, Set<String> inProgressUUIds) { + + private Resource fakePersist(Resource agentSideResource, InventoryStatus requiredInventoryStatus, + Set<String> inProgressUUIds) { Resource persisted = resourceStore.get(agentSideResource.getUuid()); if (!inProgressUUIds.add(agentSideResource.getUuid())) { return persisted; @@ -237,94 +241,114 @@ public class FakeServerInventory { persisted.setInventoryStatus(requiredInventoryStatus); persisted.setResourceKey(agentSideResource.getResourceKey()); persisted.setResourceType(agentSideResource.getResourceType()); - + Resource parent = agentSideResource.getParentResource(); if (parent != null && parent != Resource.ROOT) { - persisted.setParentResource(fakePersist(agentSideResource.getParentResource(), requiredInventoryStatus, inProgressUUIds)); + persisted.setParentResource(fakePersist(agentSideResource.getParentResource(), requiredInventoryStatus, + inProgressUUIds)); } else { persisted.setParentResource(parent); }
Set<Resource> childResources = new HashSet<Resource>(); persisted.setChildResources(childResources); - for(Resource child : agentSideResource.getChildResources()) { + for (Resource child : agentSideResource.getChildResources()) { childResources.add(fakePersist(child, requiredInventoryStatus, inProgressUUIds)); } - + inProgressUUIds.remove(agentSideResource.getUuid()); - + return persisted; } - + private ResourceSyncInfo getSyncInfo() { return platform != null ? convert(platform) : null; } - + private void throwIfFailing() { if (failing) { throw new RuntimeException("Fake server inventory is in the failing mode."); } } - + private static ResourceSyncInfo convert(Resource root) { + return convertInternal(root, new HashMap<String, ResourceSyncInfo>()); + } + + private static ResourceSyncInfo convertInternal(Resource root, Map<String, ResourceSyncInfo> intermediateResults) { + ResourceSyncInfo ret = intermediateResults.get(root.getUuid()); + + if (ret != null) { + return ret; + } + try { - ResourceSyncInfo ret = new ResourceSyncInfo(); - + ret = new ResourceSyncInfo(); + + intermediateResults.put(root.getUuid(), ret); + Class<ResourceSyncInfo> clazz = ResourceSyncInfo.class;
getPrivateField(clazz, "id").set(ret, root.getId()); getPrivateField(clazz, "uuid").set(ret, root.getUuid()); getPrivateField(clazz, "mtime").set(ret, root.getMtime()); getPrivateField(clazz, "inventoryStatus").set(ret, root.getInventoryStatus()); - getPrivateField(clazz, "parent").set(ret, null); - + + ResourceSyncInfo parent = root.getParentResource() == null ? null : convertInternal( + root.getParentResource(), intermediateResults); + + getPrivateField(clazz, "parent").set(ret, parent); + Set<ResourceSyncInfo> children = new LinkedHashSet<ResourceSyncInfo>(); - for(Resource child : root.getChildResources()) { - ResourceSyncInfo syncChild = convert(child); - getPrivateField(clazz, "parent").set(syncChild, ret); - - children.add(convert(child)); - } + for (Resource child : root.getChildResources()) { + ResourceSyncInfo syncChild = convertInternal(child, intermediateResults); + + children.add(syncChild); + } getPrivateField(clazz, "childSyncInfos").set(ret, children); - + return ret; } catch (Exception e) { fail("Failed to convert resource " + root + " to a ResourceSyncInfo. This should not happen.", e); return null; } - } - + } + private static Field getPrivateField(Class<?> clazz, String fieldName) throws NoSuchFieldException { Field field = clazz.getDeclaredField(fieldName); if (!field.isAccessible()) { field.setAccessible(true); } - + return field; } - + private static Resource findResource(Resource root, Resource template, Comparator<Resource> comparator) { - if (root == null) return null; + if (root == null) + return null; if (comparator.compare(root, template) == 0) { return root; } else { - for(Resource child : root.getChildResources()) { + for (Resource child : root.getChildResources()) { Resource found = findResource(child, template, comparator); - if (found != null) return found; + if (found != null) + return found; } } - + return null; - } - - private static void findResources(Resource root, Resource template, Set<Resource> result, Comparator<Resource> comparator) { - if (root == null) return; + } + + private static void findResources(Resource root, Resource template, Set<Resource> result, + Comparator<Resource> comparator) { + if (root == null) + return; if (comparator.compare(root, template) == 0) { result.add(root); } else { - for(Resource child : root.getChildResources()) { + for (Resource child : root.getChildResources()) { findResources(child, template, result, comparator); } - } + } } } diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java index 25eca30..5949b76 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java @@ -19,11 +19,29 @@
package org.rhq.core.pc.upgrade;
+import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set;
+import org.jmock.Expectations; +import org.jmock.Mockery; import org.testng.annotations.Test;
+import org.rhq.core.clientapi.server.discovery.InvalidInventoryReportException; +import org.rhq.core.clientapi.server.discovery.InventoryReport; +import org.rhq.core.domain.resource.InventoryStatus; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; + /** * The plugins and their resource types form the following dependency structure: * <pre> @@ -35,6 +53,10 @@ import org.testng.annotations.Test; * </pre> * The dependencies in the above "chart" are formed using either the <code><runs-inside></code> * or <code>sourcePlugin/sourceType</code> approaches just to test that both are handled correctly. + * <p> + * The <code>parentdep</code>, <code>parentsibling</code>, <code>test</code> and <code>sibling</code> plugins are present + * in two versions and support the {@link ResourceUpgradeFacet}, while the rest of the plugins is + * present only in single version. * * @author Lukas Krejci */ @@ -53,29 +75,149 @@ public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase private static final String TEST_V1_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-test-1.0.0.jar"; private static final String TEST_V2_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-test-2.0.0.jar";
+ private static final String UPGRADED_RESOURCE_KEY_PREFIX = "UPGRADED"; + + private static final HashMap<String, List<String>> DEPS; + + static { + DEPS = new HashMap<String, List<String>>(); + + DEPS.put(BASE_PLUGIN_NAME, Collections.<String> emptyList()); + DEPS.put(PARENT_DEP_V1_PLUGIN_NAME, Arrays.asList(BASE_PLUGIN_NAME, ROOT_PLUGIN_NAME)); + DEPS.put(PARENT_DEP_V2_PLUGIN_NAME, DEPS.get(PARENT_DEP_V1_PLUGIN_NAME)); + DEPS.put(PARENT_SIBLING_V1_PLUGIN_NAME, Arrays.asList(BASE_PLUGIN_NAME, ROOT_PLUGIN_NAME)); + DEPS.put(PARENT_SIBLING_V2_PLUGIN_NAME, DEPS.get(PARENT_SIBLING_V1_PLUGIN_NAME)); + DEPS.put(ROOT_PLUGIN_NAME, Arrays.asList(BASE_PLUGIN_NAME)); + DEPS.put(SIBLING_V1_PLUGIN_NAME, Arrays.asList(BASE_PLUGIN_NAME, ROOT_PLUGIN_NAME, PARENT_DEP_V1_PLUGIN_NAME)); + DEPS.put(SIBLING_V2_PLUGIN_NAME, Arrays.asList(BASE_PLUGIN_NAME, ROOT_PLUGIN_NAME, PARENT_DEP_V2_PLUGIN_NAME)); + DEPS.put(TEST_V1_PLUGIN_NAME, + Arrays.asList(BASE_PLUGIN_NAME, ROOT_PLUGIN_NAME, PARENT_DEP_V1_PLUGIN_NAME, SIBLING_V1_PLUGIN_NAME)); + DEPS.put(TEST_V2_PLUGIN_NAME, + Arrays.asList(BASE_PLUGIN_NAME, ROOT_PLUGIN_NAME, PARENT_DEP_V1_PLUGIN_NAME, SIBLING_V2_PLUGIN_NAME)); + } + + private static final ResType TEST_TYPE = new ResType("TestResource", "test"); + private static final ResType SIBLING_TYPE = new ResType("TestResourceSibling", "test"); + private static final ResType PARENT_TYPE = new ResType("TestResourceParent", "test"); + private static final ResType PARENT_DEP_TYPE = new ResType("ParentDependency", "parentdep"); + private static final ResType PARENT_SIBLING_TYPE = new ResType("ParentDepSibling", "parentsibling"); + private static final ResType ROOT_TYPE = new ResType("Root", "root"); + protected Collection<String> getRequiredPlugins() { return Arrays.asList(BASE_PLUGIN_NAME, PARENT_DEP_V1_PLUGIN_NAME, PARENT_DEP_V2_PLUGIN_NAME, PARENT_SIBLING_V1_PLUGIN_NAME, PARENT_SIBLING_V2_PLUGIN_NAME, ROOT_PLUGIN_NAME, SIBLING_V1_PLUGIN_NAME, SIBLING_V2_PLUGIN_NAME, TEST_V1_PLUGIN_NAME, TEST_V2_PLUGIN_NAME); } - + @Test - public void testSuccess() { - //TODO implement - //check that all the stuff is properly upgraded on success + public void testSuccess() throws Exception { + setCurrentServerSideInventory(new FakeServerInventory()); + + //let it all run in v1 + executeTestWithPlugins(getAllDepsFor(TEST_V1_PLUGIN_NAME, PARENT_SIBLING_V1_PLUGIN_NAME), + new AbstractTestPayload(true, Collections.<ResType> emptyList()) { + public void test(Map<ResType, Set<Resource>> resourceUpgradeTestResources) { + } + + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + } + }; + } + }); + + //now let's run with v2 plugins and check the layout of the inventory + executeTestWithPlugins( + getAllDepsFor(TEST_V2_PLUGIN_NAME, PARENT_SIBLING_V2_PLUGIN_NAME), + new AbstractTestPayload(false, Arrays.asList(TEST_TYPE, SIBLING_TYPE, PARENT_TYPE, PARENT_DEP_TYPE, + PARENT_SIBLING_TYPE, ROOT_TYPE)) { + + public void test(Map<ResType, Set<Resource>> resources) { + checkPresenceOfResourceTypes(resources, getExpectedResourceTypes()); + + checkNumberOfResources(resources, ROOT_TYPE, 1); + checkNumberOfResources(resources, PARENT_DEP_TYPE, 1); + checkNumberOfResources(resources, PARENT_SIBLING_TYPE, 1); + checkNumberOfResources(resources, PARENT_TYPE, 2); + checkNumberOfResources(resources, SIBLING_TYPE, 30); + checkNumberOfResources(resources, TEST_TYPE, 30); + + //check that the resources are upgraded + checkResourcesUpgraded(resources.get(PARENT_SIBLING_TYPE)); + checkResourcesUpgraded(resources.get(PARENT_TYPE)); + checkResourcesUpgraded(resources.get(SIBLING_TYPE)); + checkResourcesUpgraded(resources.get(TEST_TYPE)); + } + + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + } + }; + } + }); } - + @Test public void testFailureOnLeaf() { //TODO implement //check that the system behaves correctly if there is an upgrade failure //at the leaf node of the plugin dep graph } - + @Test public void testFailureOnDependencies() { //TODO implement //check that stuff works if there is an upgrade failure on some of the resources //in the plugin some "in the middle" of the plugin dep graph } + + @SuppressWarnings("unchecked") + @Override + protected void defineDefaultExpectations(Expectations expectations) { + super.defineDefaultExpectations(expectations); + try { + expectations.allowing(getCurrentDiscoveryServerService()) + .mergeInventoryReport(expectations.with(Expectations.any(InventoryReport.class))); + expectations.will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED)); + + expectations.allowing(getCurrentDiscoveryServerService()).upgradeResources(expectations.with(Expectations.any(Set.class))); + expectations.will(getCurrentServerSideInventory().upgradeResources()); + + expectations.allowing(getCurrentDiscoveryServerService()).postProcessNewlyCommittedResources( + expectations.with(Expectations.any(Set.class))); + + } catch (InvalidInventoryReportException e) { + //this is not going to happen because we're mocking the invocation + } + } + + private Set<String> getAllDepsFor(String... plugins) { + HashSet<String> deps = new HashSet<String>(); + for (String plugin : plugins) { + deps.add(plugin); + deps.addAll(DEPS.get(plugin)); + } + + return deps; + } + + private static void checkPresenceOfResourceTypes(Map<ResType, Set<Resource>> resources, Set<ResType> expectedTypes) { + for (ResType resType : expectedTypes) { + assertNotNull(resources.get(resType), "Expecting some resources of type " + resType); + } + } + + private static void checkNumberOfResources(Map<ResType, Set<Resource>> resources, ResType type, int count) { + assertEquals(resources.get(type).size(), count, "Unexpected number of " + type + " discovered."); + } + + private static void checkResourcesUpgraded(Set<Resource> resources) { + for(Resource res : resources) { + assertTrue(res.getResourceKey().startsWith(UPGRADED_RESOURCE_KEY_PREFIX), "Resource " + res + " doesn't seem to be upgraded even though it should."); + } + } } diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index 8cfec36..d47d00c 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -31,6 +31,8 @@ import java.io.File; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.Set;
import org.jmock.Expectations; @@ -54,8 +56,13 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { private static final String PLUGIN_V2_FILENAME = "/resource-upgrade-test-plugin-2.0.0.jar"; private static final String FAILING_PLUGIN_FILE_NAME = "/resource-upgrade-test-plugin-3.0.0.jar";
- static final String SINGLETON_RESOURCE_TYPE_NAME = "Resource"; - static final String SINGLETON_RESOURCE_TYPE_PLUGIN_NAME = "ResourceUpgradeTest"; + private static final String SINGLETON_RESOURCE_TYPE_NAME = "Resource"; + private static final String SINGLETON_RESOURCE_TYPE_PLUGIN_NAME = "ResourceUpgradeTest"; + private static final ResType SINGLETON_TYPE = new ResType(SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME); + + private static List<ResType> getMyExpectedTypes() { + return Arrays.asList(SINGLETON_TYPE); + }
protected Collection<String> getRequiredPlugins() { return Arrays.asList(PLUGIN_V1_FILENAME, PLUGIN_V2_FILENAME, FAILING_PLUGIN_FILE_NAME); @@ -66,11 +73,11 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.NEW);
- TestPayload testNoChange = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { - public void test(Set<Resource> discoveredResources) { + TestPayload testNoChange = new AbstractTestPayload(false, getMyExpectedTypes()) { + public void test(Map<ResType, Set<Resource>> discoveredResources) { assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found.");
- Resource discoveredResource = discoveredResources.iterator().next(); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next();
assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); assertEquals(discoveredResource.getName(), "resource-name-v1"); @@ -111,11 +118,11 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase {
getCurrentServerSideInventory().setFailing(true);
- TestPayload test = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { - public void test(Set<Resource> discoveredResources) { + TestPayload test = new AbstractTestPayload(false, getMyExpectedTypes()) { + public void test(Map<ResType, Set<Resource>> discoveredResources) { assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found.");
- Resource discoveredResource = discoveredResources.iterator().next(); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next();
assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); assertEquals(discoveredResource.getName(), "resource-name-v1"); @@ -145,11 +152,11 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.COMMITTED);
- TestPayload test = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { - public void test(Set<Resource> discoveredResources) { + TestPayload test = new AbstractTestPayload(false, getMyExpectedTypes()) { + public void test(Map<ResType, Set<Resource>> discoveredResources) { assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found.");
- Resource discoveredResource = discoveredResources.iterator().next(); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next();
assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); assertEquals(discoveredResource.getName(), "resource-name-v2"); @@ -193,11 +200,11 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.COMMITTED);
- TestPayload test = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { - public void test(Set<Resource> resourceUpgradeTestResources) { + TestPayload test = new AbstractTestPayload(false, getMyExpectedTypes()) { + public void test(Map<ResType, Set<Resource>> resourceUpgradeTestResources) { assertEquals(resourceUpgradeTestResources.size(), 1, "Expected single test resource but multiple found.");
- Resource discoveredResource = resourceUpgradeTestResources.iterator().next(); + Resource discoveredResource = resourceUpgradeTestResources.get(SINGLETON_TYPE).iterator().next();
assertTrue(discoveredResource.getResourceErrors().size() > 0, "There should be upgrade errors persisted on the server side.");
@@ -231,11 +238,11 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase {
private void initialSyncAndDiscovery(final InventoryStatus requiredInventoryStatus) throws Exception { cleanDataDir(); - executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), new AbstractTestPayload(true, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { - public void test(Set<Resource> discoveredResources) { + executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), new AbstractTestPayload(true, getMyExpectedTypes()) { + public void test(Map<ResType, Set<Resource>> discoveredResources) { assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found.");
- Resource discoveredResource = discoveredResources.iterator().next(); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next();
assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); assertEquals(discoveredResource.getName(), "resource-name-v1"); @@ -260,11 +267,11 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { private void upgradeTest(boolean clearInventoryDat) throws Exception { initialSyncAndDiscovery(InventoryStatus.COMMITTED);
- executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), new AbstractTestPayload(clearInventoryDat, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { - public void test(Set<Resource> discoveredResources) { + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), new AbstractTestPayload(clearInventoryDat, getMyExpectedTypes()) { + public void test(Map<ResType, Set<Resource>> discoveredResources) { assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found.");
- Resource discoveredResource = discoveredResources.iterator().next(); + Resource discoveredResource = discoveredResources.get(SINGLETON_TYPE).iterator().next();
assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); assertEquals(discoveredResource.getName(), "resource-name-v2"); diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java index 3aa772b..0aefafd 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java @@ -25,6 +25,9 @@ import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Set;
import org.apache.commons.io.FileUtils; @@ -73,6 +76,78 @@ public abstract class ResourceUpgradeTestBase { private ResourceFactoryServerService currentResourceFactoryServerService; private FakeServerInventory currentServerSideInventory;
+ protected static class ResType { + private String resourceTypeName; + private String resourceTypePluginName; + + public ResType(String resourceTypeName, String resourceTypePluginName) { + super(); + this.resourceTypeName = resourceTypeName; + this.resourceTypePluginName = resourceTypePluginName; + } + + public String getResourceTypeName() { + return resourceTypeName; + } + + public String getResourceTypePluginName() { + return resourceTypePluginName; + } + + @Override + public int hashCode() { + return resourceTypeName.hashCode() * resourceTypePluginName.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof ResType)) { + return false; + } + + ResType o = (ResType)other; + + return resourceTypeName.equals(o.getResourceTypeName()) && resourceTypePluginName.equals(o.getResourceTypePluginName()); + } + + @Override + public String toString() { + return "ResType[name='" + resourceTypeName + "', plugin='" + resourceTypePluginName + "']"; + } + } + + protected interface TestPayload { + Expectations getExpectations(Mockery context) throws Exception; + + void test(Map<ResType,Set<Resource>> resourceUpgradeTestResources); + + boolean isClearInventoryDat(); + + Set<ResType> getExpectedResourceTypes(); + } + + protected static abstract class AbstractTestPayload implements TestPayload { + private boolean clearInventoryDat; + private Set<ResType> resourceTypes; + + public AbstractTestPayload(boolean clearInventoryDat, Collection<ResType> resourceTypes) { + this.clearInventoryDat = clearInventoryDat; + this.resourceTypes = new HashSet<ResType>(resourceTypes); + } + + public boolean isClearInventoryDat() { + return clearInventoryDat; + } + + public Set<ResType> getExpectedResourceTypes() { + return resourceTypes; + } + } + @BeforeClass public void init() { tmpDir = getTmpDirectory(); @@ -81,21 +156,21 @@ public abstract class ResourceUpgradeTestBase { dataDir = new File(tmpDir, DATA_DIR_NAME); assertTrue(dataDir.mkdir(), "Could not create plugin container data directory."); } - + @BeforeClass public void verifyPluginsExist() { for (String plugin : getRequiredPlugins()) { verifyPluginExists(plugin); } } - + @AfterClass public void undeployPlugins() throws IOException { FileUtils.deleteDirectory(tmpDir); } - + protected abstract Collection<String> getRequiredPlugins(); - + protected void setCurrentServerSideInventory(FakeServerInventory currentServerSideInventory) { this.currentServerSideInventory = currentServerSideInventory; } @@ -103,8 +178,9 @@ public abstract class ResourceUpgradeTestBase { protected FakeServerInventory getCurrentServerSideInventory() { return currentServerSideInventory; } - - protected void setCurrentResourceFactoryServerService(ResourceFactoryServerService currentResourceFactoryServerService) { + + protected void setCurrentResourceFactoryServerService( + ResourceFactoryServerService currentResourceFactoryServerService) { this.currentResourceFactoryServerService = currentResourceFactoryServerService; }
@@ -178,24 +254,24 @@ public abstract class ResourceUpgradeTestBase {
protected static File getTmpDirectory() { File ret = new File(System.getProperty("java.io.tmpdir"), "resource-upgrade-test" + System.currentTimeMillis()); - + while (ret.exists() || !ret.mkdir()) { ret = new File(System.getProperty("java.io.tmpdir"), "resource-upgrade-test" + System.currentTimeMillis()); } - + return ret; }
private PluginContainerConfiguration createPluginContainerConfiguration(Mockery context) throws Exception { PluginContainerConfiguration conf = new PluginContainerConfiguration(); - + conf.setPluginDirectory(new File(tmpDir, PLUGINS_DIR_NAME)); conf.setDataDirectory(new File(tmpDir, DATA_DIR_NAME)); conf.setTemporaryDirectory(new File(tmpDir, TMP_DIR_NAME)); conf.setInsideAgent(true); //pc must think it's inside an agent so that it persists the inventory between restarts conf.setPluginFinder(new FileSystemPluginFinder(conf.getPluginDirectory())); - conf.setCreateResourceClassloaders(false); - + conf.setCreateResourceClassloaders(false); + //we're not interested in any scans happening out of our control conf.setAvailabilityScanInitialDelay(Long.MAX_VALUE); conf.setConfigurationDiscoveryInitialDelay(Long.MAX_VALUE); @@ -204,7 +280,7 @@ public abstract class ResourceUpgradeTestBase { conf.setMeasurementCollectionInitialDelay(Long.MAX_VALUE); conf.setServerDiscoveryInitialDelay(Long.MAX_VALUE); conf.setServiceDiscoveryInitialDelay(Long.MAX_VALUE); - + setCurrentBundleServerService(context.mock(BundleServerService.class)); setCurrentConfigurationServerService(context.mock(ConfigurationServerService.class)); setCurrentContentServerService(context.mock(ContentServerService.class)); @@ -214,7 +290,7 @@ public abstract class ResourceUpgradeTestBase { setCurrentMeasurementServerService(context.mock(MeasurementServerService.class)); setCurrentOperationServerService(context.mock(OperationServerService.class)); setCurrentResourceFactoryServerService(context.mock(ResourceFactoryServerService.class)); - + ServerServices serverServices = new ServerServices(); serverServices.setBundleServerService(getCurrentBundleServerService()); serverServices.setConfigurationServerService(getCurrentConfigurationServerService()); @@ -225,9 +301,9 @@ public abstract class ResourceUpgradeTestBase { serverServices.setMeasurementServerService(getCurrentMeasurementServerService()); serverServices.setOperationServerService(getCurrentOperationServerService()); serverServices.setResourceFactoryServerService(getCurrentResourceFactoryServerService()); - + conf.setServerServices(serverServices); - + return conf; }
@@ -236,104 +312,76 @@ public abstract class ResourceUpgradeTestBase { */ protected void verifyPluginExists(String pluginResourcePath) { URL url = getClass().getResource(pluginResourcePath); - + File pluginFile = FileUtils.toFile(url); - + assertTrue(pluginFile.exists(), pluginFile.getAbsoluteFile() + " plugin jar could not be found."); }
private void copyPlugin(String pluginResourcePath, File pluginDirectory) throws IOException { URL pluginUrl = getClass().getResource(pluginResourcePath); - + File pluginFile = new File(pluginResourcePath); String pluginFileName = pluginFile.getName(); - - FileUtils.copyURLToFile(pluginUrl, new File(pluginDirectory, pluginFileName)); - } - - protected interface TestPayload { - Expectations getExpectations(Mockery context) throws Exception; - void test(Set<Resource> resourceUpgradeTestResources); - boolean isClearInventoryDat(); - String getResourceTypeName(); - String getResourceTypePluginName(); - } - - protected static abstract class AbstractTestPayload implements TestPayload { - private boolean clearInventoryDat; - private String resourceTypeName; - private String resourceTypePluginName; - - public AbstractTestPayload(boolean clearInventoryDat, String resourceTypeName, String resourceTypePluginName) { - this.clearInventoryDat = clearInventoryDat; - this.resourceTypeName = resourceTypeName; - this.resourceTypePluginName = resourceTypePluginName; - } - - public boolean isClearInventoryDat() { - return clearInventoryDat; - } - - public String getResourceTypeName() { - return resourceTypeName; - } - - public String getResourceTypePluginName() { - return resourceTypePluginName; - } - }
- /** - * - */ - public ResourceUpgradeTestBase() { - super(); + FileUtils.copyURLToFile(pluginUrl, new File(pluginDirectory, pluginFileName)); }
private Set<Resource> getTestingResources(String resourceTypeName, String resourceTypePluginName) { - ResourceType resType = PluginContainer.getInstance().getPluginManager().getMetadataManager().getType(resourceTypeName, resourceTypePluginName); - + ResourceType resType = PluginContainer.getInstance().getPluginManager().getMetadataManager() + .getType(resourceTypeName, resourceTypePluginName); + return getCurrentServerSideInventory().findResourcesByType(resType); }
protected void executeTestWithPlugins(Set<String> pluginResourcePaths, TestPayload test) throws Exception { FileUtils.cleanDirectory(new File(tmpDir, PLUGINS_DIR_NAME)); - - for(String pluginResourcePath : pluginResourcePaths) { + + for (String pluginResourcePath : pluginResourcePaths) { copyPlugin(pluginResourcePath, pluginDir); } - + Mockery context = new Mockery(); - + PluginContainerConfiguration pcConfig = createPluginContainerConfiguration(context); - + if (test.isClearInventoryDat()) { File inventoryDat = new File(pcConfig.getDataDirectory(), "inventory.dat"); inventoryDat.delete(); } - + context.checking(test.getExpectations(context)); - + PluginContainer.getInstance().setConfiguration(pcConfig); PluginContainer.getInstance().initialize(); - + try { //give the pc the time to finish resource upgrade Thread.sleep(1000); - + //execute full discovery InventoryManager im = PluginContainer.getInstance().getInventoryManager(); im.executeServerScanImmediately(); - im.executeServiceScanImmediately(); - - Set<Resource> resources = getTestingResources(test.getResourceTypeName(), test.getResourceTypePluginName()); - + + //do the service scan a couple of times so that we can commit + //the resources deep in the type hierarchy + for(int i = 0; i < 10; ++i) { + im.executeServiceScanImmediately(); + } + + Map<ResType, Set<Resource>> resources = new HashMap<ResType, Set<Resource>>(); + + for(ResType type : test.getExpectedResourceTypes()) { + Set<Resource> rs = getTestingResources(type.getResourceTypeName(), type.getResourceTypePluginName()); + resources.put(type, rs); + } + test.test(resources); - + context.assertIsSatisfied(); } finally { - PluginContainer.getInstance().shutdown(); - } + PluginContainer.getInstance().shutdown(); + } }
@SuppressWarnings("unchecked") @@ -346,11 +394,13 @@ public abstract class ResourceUpgradeTestBase { expectations.ignoring(getCurrentMeasurementServerService()); expectations.ignoring(getCurrentOperationServerService()); expectations.ignoring(getCurrentResourceFactoryServerService()); - + //just ignore these invocations if we get a availability scan in the PC... - expectations.allowing(getCurrentDiscoveryServerService()).mergeAvailabilityReport(expectations.with(Expectations.any(AvailabilityReport.class))); - - expectations.allowing(getCurrentDiscoveryServerService()).getResources(expectations.with(Expectations.any(Set.class)), expectations.with(Expectations.any(boolean.class))); + expectations.allowing(getCurrentDiscoveryServerService()).mergeAvailabilityReport( + expectations.with(Expectations.any(AvailabilityReport.class))); + + expectations.allowing(getCurrentDiscoveryServerService()).getResources( + expectations.with(Expectations.any(Set.class)), expectations.with(Expectations.any(boolean.class))); expectations.will(getCurrentServerSideInventory().getResources()); }
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseDiscoveryComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseDiscoveryComponent.java index 61d4fe0..a03dff5 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseDiscoveryComponent.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseDiscoveryComponent.java @@ -46,15 +46,25 @@ public class BaseDiscoveryComponent<T extends ResourceComponent> implements Reso String keyTemplate = pluginConfig.getSimpleValue("key", null); int count = pluginConfig.getSimple("count").getIntegerValue();
- int parentN = context.getParentResourceContext().getPluginConfiguration().getSimple("ordinal") - .getIntegerValue(); + int parentN = 0; + + if (context.getParentResourceContext() != null) { + PropertySimple parentOrdinalProperty = context.getParentResourceContext().getPluginConfiguration() + .getSimple("ordinal"); + + if (parentOrdinalProperty != null) { + parentN = parentOrdinalProperty.getIntegerValue(); + } + }
for (int i = 0; i < count; ++i) {
String key = getResourceKey(keyTemplate, i, parentN);
+ pluginConfig = context.getDefaultPluginConfiguration(); + pluginConfig.put(new PropertySimple("ordinal", i)); - + DiscoveredResourceDetails detail = new DiscoveredResourceDetails(context.getResourceType(), key, key, null, null, pluginConfig, null);
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java index beb36db..ec1cb20 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java @@ -28,34 +28,36 @@ import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; * * @author Lukas Krejci */ -public class BaseUpgradingDiscoveryComponent<T extends BaseResourceComponent> extends BaseDiscoveryComponent<T> implements ResourceUpgradeFacet<T> { +public class BaseUpgradingDiscoveryComponent<T extends BaseResourceComponent> extends BaseDiscoveryComponent<T> + implements ResourceUpgradeFacet<T> {
public ResourceUpgradeReport upgrade(ResourceUpgradeContext<T> inventoriedResource) { Configuration pluginConfig = inventoriedResource.getPluginConfiguration(); - + BaseResourceComponent<?> parent = inventoriedResource.getParentResourceComponent(); int ordinal = pluginConfig.getSimple("ordinal").getIntegerValue(); int parentOrdinal = parent == null ? 0 : parent.getOrdinal(); - + boolean fail = Boolean.getBoolean(pluginConfig.getSimpleValue("failUpgrade", "false")); - + if (!fail && parent != null) { fail = parent.getChildrenToFailUpgrade().contains(Integer.valueOf(ordinal)); } - + if (fail) { throw new RuntimeException("Failing the resource upgrade purposefully."); } - + String newKey = pluginConfig.getSimpleValue("upgradedKey", null); - + if (newKey == null) { return null; } - + ResourceUpgradeReport report = new ResourceUpgradeReport(); - + report.setNewResourceKey(getResourceKey(newKey, ordinal, parentOrdinal)); - return null; + + return report; } } diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml index f5e6920..608793c 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml @@ -22,8 +22,8 @@
<plugin-configuration> <c:simple-property name="count" default="1" /> - <c:simple-property name="key" default="test-resource-parent-sibling-%n,parent-%p" /> - <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-parent-sibling-%n,parent-%p" /> + <c:simple-property name="key" default="test-resource-parent-dep-sibling-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-parent-dep-sibling-%n,parent-%p" /> </plugin-configuration>
</server> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml index d138066..ddda11a 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml @@ -22,7 +22,7 @@
<plugin-configuration> <c:simple-property name="count" default="1" /> - <c:simple-property name="key" default="UPGRADED-test-resource-parent-sibling-%n,parent-%p" /> + <c:simple-property name="key" default="UPGRADED-test-resource-parent-dep-sibling-%n,parent-%p" /> </plugin-configuration>
</server> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml index 44a1033..d3ea7b7 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml @@ -11,10 +11,18 @@
<depends plugin="base" useClasses="true"/>
- <!-- This service is put in the type hierarchy in the v1/v2 test plugins --> - <service name="TestResourceSibling" - discovery="BaseDiscoveryComponent" - class="BaseResourceComponent" /> + <server name="Bogus" class="BaseDiscoveryComponent"> + <!-- This service is put in the type hierarchy in the v1/v2 test plugins --> + <service name="TestResourceSibling" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + <plugin-configuration> + <c:simple-property name="count" default="10" /> + <c:simple-property name="key" default="test-resource-sibling-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> + </plugin-configuration> + </service>
+ </server> </plugin>
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml index aeab68f..f7f7a2c 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml @@ -10,10 +10,16 @@
<depends plugin="base" useClasses="true"/>
+ <server name="Bogus" class="BaseDiscoveryComponent"> <!-- This service is put in the type hierarchy in the v1/v2 test plugins --> <service name="TestResourceSibling" discovery="BaseUpgradingDiscoveryComponent" - class="BaseResourceComponent" /> - + class="BaseResourceComponent"> + <plugin-configuration> + <c:simple-property name="count" default="15" /> <!-- This intentionally differs from v1 --> + <c:simple-property name="key" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> + </plugin-configuration> + </service> + </server> </plugin>
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml index e934494..ebe9793 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml @@ -37,13 +37,8 @@ </plugin-configuration> </service>
- <service name="TestResourceSibling" sourcePlugin="sibling" sourceType="TestResourceSibling"> - <plugin-configuration> - <c:simple-property name="count" default="10" /> - <c:simple-property name="key" default="test-resource-sibling-%n,parent-%p" /> - <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> - </plugin-configuration> - </service> + <service name="TestResourceSibling" sourcePlugin="sibling" sourceType="TestResourceSibling" + class="BaseResourceComponent" discovery="BaseDiscoveryComponent" /> </server>
</plugin> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml index 96658e3..3d709b0 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml @@ -26,7 +26,7 @@ </plugin-configuration>
<service name="TestResource" - discovery="BaseDiscoveryComponent" + discovery="BaseUpgradingDiscoveryComponent" class="BaseResourceComponent"> <plugin-configuration> <c:simple-property name="count" default="15" /> <!-- This intentionally differs from v1 --> @@ -35,13 +35,8 @@
</service>
- <service name="TestResourceSibling" sourcePlugin="sibling" sourceType="TestResourceSibling"> - <plugin-configuration> - <c:simple-property name="count" default="15" /> <!-- This intentionally differs from v1 --> - <c:simple-property name="key" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> - </plugin-configuration> - </service> - + <service name="TestResourceSibling" sourcePlugin="sibling" sourceType="TestResourceSibling" + class="BaseResourceComponent" discovery="BaseUpgradingDiscoveryComponent" /> </server>
</plugin>
commit c99d68dd036f243a2f28e000e10385d27bbdb785 Author: Lukas Krejci lkrejci@redhat.com Date: Wed Sep 29 13:53:45 2010 +0200
Adding a skeleton of what will need to be tested for upgrade failure handling.
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java new file mode 100644 index 0000000..25eca30 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeFailureHandlingTest.java @@ -0,0 +1,81 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade; + +import java.util.Arrays; +import java.util.Collection; + +import org.testng.annotations.Test; + +/** + * The plugins and their resource types form the following dependency structure: + * <pre> + * Root(root) + * / \ + * ParentDependency(parentdep) ParentDepSibling(parentsibling) + * / \ + * TestResource(test) TestResourceSibling(sibling) + * </pre> + * The dependencies in the above "chart" are formed using either the <code><runs-inside></code> + * or <code>sourcePlugin/sourceType</code> approaches just to test that both are handled correctly. + * + * @author Lukas Krejci + */ +@Test(sequential = true, invocationCount = 1) +public class ResourceUpgradeFailureHandlingTest extends ResourceUpgradeTestBase { + + //plugin names + private static final String BASE_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-base-1.0.0.jar"; + private static final String PARENT_DEP_V1_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-parentdep-1.0.0.jar"; + private static final String PARENT_DEP_V2_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-parentdep-2.0.0.jar"; + private static final String PARENT_SIBLING_V1_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-parentsibling-1.0.0.jar"; + private static final String PARENT_SIBLING_V2_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-parentsibling-2.0.0.jar"; + private static final String ROOT_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-root-1.0.0.jar"; + private static final String SIBLING_V1_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-sibling-1.0.0.jar"; + private static final String SIBLING_V2_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-sibling-2.0.0.jar"; + private static final String TEST_V1_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-test-1.0.0.jar"; + private static final String TEST_V2_PLUGIN_NAME = "/resource-upgrade-test-plugin-multi-test-2.0.0.jar"; + + protected Collection<String> getRequiredPlugins() { + return Arrays.asList(BASE_PLUGIN_NAME, PARENT_DEP_V1_PLUGIN_NAME, PARENT_DEP_V2_PLUGIN_NAME, + PARENT_SIBLING_V1_PLUGIN_NAME, PARENT_SIBLING_V2_PLUGIN_NAME, ROOT_PLUGIN_NAME, SIBLING_V1_PLUGIN_NAME, + SIBLING_V2_PLUGIN_NAME, TEST_V1_PLUGIN_NAME, TEST_V2_PLUGIN_NAME); + } + + @Test + public void testSuccess() { + //TODO implement + //check that all the stuff is properly upgraded on success + } + + @Test + public void testFailureOnLeaf() { + //TODO implement + //check that the system behaves correctly if there is an upgrade failure + //at the leaf node of the plugin dep graph + } + + @Test + public void testFailureOnDependencies() { + //TODO implement + //check that stuff works if there is an upgrade failure on some of the resources + //in the plugin some "in the middle" of the plugin dep graph + } +}
commit 4f504f582fc9040bcf5ed7f7dd24cfd3bc2adbad Author: Lukas Krejci lkrejci@redhat.com Date: Wed Sep 29 13:49:24 2010 +0200
some more minor changes to class structure and plugin names.
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml index 035bf36..4d6e753 100644 --- a/modules/core/plugin-container/pom.xml +++ b/modules/core/plugin-container/pom.xml @@ -281,7 +281,7 @@ <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/v1/org/rhq/core/pc/upgrade/plugins/multi/v1"> <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/v1/*.class" /> </copy> --> - <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-1.0.0.jar"> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-test-1.0.0.jar"> <fileset dir="${project.build.testOutputDirectory}/tmp/multi/v1" includes="**/*.class,**/rhq-plugin.xml" /> </jar>
@@ -291,7 +291,7 @@ <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/v2/org/rhq/core/pc/upgrade/plugins/multi/v2"> <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/v2/*.class" /> </copy> --> - <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-2.0.0.jar"> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-test-2.0.0.jar"> <fileset dir="${project.build.testOutputDirectory}/tmp/multi/v2" includes="**/*.class,**/rhq-plugin.xml" /> </jar>
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index e13ea3d..8cfec36 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -28,6 +28,8 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue;
import java.io.File; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Set;
@@ -38,7 +40,6 @@ import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; import org.rhq.core.pc.PluginContainer; import org.rhq.core.pc.inventory.ResourceContainer; -import org.testng.annotations.BeforeClass; import org.testng.annotations.Test;
/** @@ -56,11 +57,8 @@ public class ResourceUpgradeTest extends ResourceUpgradeTestBase { static final String SINGLETON_RESOURCE_TYPE_NAME = "Resource"; static final String SINGLETON_RESOURCE_TYPE_PLUGIN_NAME = "ResourceUpgradeTest";
- @BeforeClass - public void sanityCheck() { - verifyPluginExists(PLUGIN_V1_FILENAME); - verifyPluginExists(PLUGIN_V2_FILENAME); - verifyPluginExists(FAILING_PLUGIN_FILE_NAME); + protected Collection<String> getRequiredPlugins() { + return Arrays.asList(PLUGIN_V1_FILENAME, PLUGIN_V2_FILENAME, FAILING_PLUGIN_FILE_NAME); }
@Test diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java index f03f2a4..3aa772b 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java @@ -24,6 +24,7 @@ import static org.testng.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.net.URL; +import java.util.Collection; import java.util.Set;
import org.apache.commons.io.FileUtils; @@ -53,7 +54,7 @@ import org.testng.annotations.BeforeClass; * * @author Lukas Krejci */ -public class ResourceUpgradeTestBase { +public abstract class ResourceUpgradeTestBase {
private static final String PLUGINS_DIR_NAME = "plugins"; private static final String DATA_DIR_NAME = "data"; @@ -81,11 +82,20 @@ public class ResourceUpgradeTestBase { assertTrue(dataDir.mkdir(), "Could not create plugin container data directory."); }
+ @BeforeClass + public void verifyPluginsExist() { + for (String plugin : getRequiredPlugins()) { + verifyPluginExists(plugin); + } + } + @AfterClass public void undeployPlugins() throws IOException { FileUtils.deleteDirectory(tmpDir); }
+ protected abstract Collection<String> getRequiredPlugins(); + protected void setCurrentServerSideInventory(FakeServerInventory currentServerSideInventory) { this.currentServerSideInventory = currentServerSideInventory; }
commit b97e79bcbd5c557fba29030f7aa0f8b4c629c56f Author: Lukas Krejci lkrejci@redhat.com Date: Wed Sep 29 13:48:28 2010 +0200
Simplify plugin names, declare correct discovery components for upgrade failure test plugins.
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/rhq-plugin.xml index 7edfba1..d262c75 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/rhq-plugin.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<plugin name="ResourceUpgradeMultiTestBase" +<plugin name="base" displayName="" description="" package="org.rhq.core.pc.upgrade.plugins.multi.base" diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/rhq-plugin.xml index 3612974..8cadc84 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/rhq-plugin.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?>
-<plugin name="ResourceUpgradeMultiTestParentDep" +<plugin name="parentdep" displayName="Resource Upgrade Multi Test" description="Resource Upgrade Multi Test" package="org.rhq.core.pc.upgrade.plugins.multi.base" @@ -9,15 +9,15 @@ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
- <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> - <depends plugin="ResourceUpgradeMultiTestRoot"/> + <depends plugin="base" useClasses="true"/> + <depends plugin="root"/>
<server name="ParentDependency" discovery="BaseDiscoveryComponent" class="BaseResourceComponent">
<runs-inside> - <parent-resource-type name="Root" plugin="ResourceUpgradeMultiTestRoot"/> + <parent-resource-type name="Root" plugin="root"/> </runs-inside>
<plugin-configuration> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/rhq-plugin.xml index 6b95114..8169122 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/rhq-plugin.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?>
-<plugin name="ResourceUpgradeMultiTestParentDep" +<plugin name="parentdep" displayName="Resource Upgrade Multi Test" description="Resource Upgrade Multi Test" package="org.rhq.core.pc.upgrade.plugins.multi.base" @@ -9,15 +9,15 @@ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
- <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> - <depends plugin="ResourceUpgradeMultiTestRoot"/> + <depends plugin="base" useClasses="true"/> + <depends plugin="root"/>
<server name="ParentDependency" - discovery="BaseDiscoveryComponent" + discovery="BaseUpgradingDiscoveryComponent" class="BaseResourceComponent">
<runs-inside> - <parent-resource-type name="Root" plugin="ResourceUpgradeMultiTestRoot"/> + <parent-resource-type name="Root" plugin="root"/> </runs-inside>
<plugin-configuration> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml index fbade54..f5e6920 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?>
-<plugin name="ResourceUpgradeMultiTestParentSibling" +<plugin name="parentsibling" displayName="Resource Upgrade Multi Test" description="Resource Upgrade Multi Test" package="org.rhq.core.pc.upgrade.plugins.multi.base" @@ -9,15 +9,15 @@ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
- <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> - <depends plugin="ResourceUpgradeMultiTestRoot"/> + <depends plugin="base" useClasses="true"/> + <depends plugin="root"/>
<server name="ParentDepSibling" discovery="BaseDiscoveryComponent" class="BaseResourceComponent">
<runs-inside> - <parent-resource-type name="Root" plugin="ResourceUpgradeMultiTestRoot"/> + <parent-resource-type name="Root" plugin="root"/> </runs-inside>
<plugin-configuration> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml index f16d526..d138066 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?>
-<plugin name="ResourceUpgradeMultiTestParentSibling" +<plugin name="parentsibling" displayName="Resource Upgrade Multi Test" description="Resource Upgrade Multi Test" package="org.rhq.core.pc.upgrade.plugins.multi.base" @@ -9,15 +9,15 @@ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
- <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> - <depends plugin="ResourceUpgradeMultiTestRoot"/> + <depends plugin="base" useClasses="true"/> + <depends plugin="root"/>
<server name="ParentDepSibling" - discovery="BaseDiscoveryComponent" + discovery="BaseUpgradingDiscoveryComponent" class="BaseResourceComponent">
<runs-inside> - <parent-resource-type name="Root" plugin="ResourceUpgradeMultiTestRoot"/> + <parent-resource-type name="Root" plugin="root"/> </runs-inside>
<plugin-configuration> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/root/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/root/rhq-plugin.xml index b5efbb1..e95c9bd 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/root/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/root/rhq-plugin.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?>
-<plugin name="ResourceUpgradeMultiTestRoot" +<plugin name="root" displayName="" description="" package="org.rhq.core.pc.upgrade.plugins.multi.base" @@ -9,6 +9,8 @@ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
+ <depends plugin="base" useClasses="true"/> + <server name="Root" discovery="BaseDiscoveryComponent" class="BaseResourceComponent"> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml index f87ef4d..44a1033 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?>
-<plugin name="ResourceUpgradeMultiTestSibling" +<plugin name="sibling" displayName="Resource Upgrade Multi Test" description="Resource Upgrade Multi Test" package="org.rhq.core.pc.upgrade.plugins.multi.base" @@ -9,30 +9,12 @@ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
- <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> - <depends plugin="ResourceUpgradeMultiTestParentDep"/> + <depends plugin="base" useClasses="true"/>
- <server name="TestResourceParentSibling" - discovery="BaseDiscoveryComponent" - class="BaseResourceComponent"> - - <plugin-configuration> - <c:simple-property name="count" default="2" /> - <c:simple-property name="key" default="test-resource-parent-sibling-%n,parent-%p" /> - <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-parent-sibling-%n,parent-%p" /> - </plugin-configuration> - - <service name="TestResourceSibling" + <!-- This service is put in the type hierarchy in the v1/v2 test plugins --> + <service name="TestResourceSibling" discovery="BaseDiscoveryComponent" - class="BaseResourceComponent"> - <plugin-configuration> - <c:simple-property name="count" default="10" /> - <c:simple-property name="key" default="test-resource-sibling-%n,parent-%p" /> - <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> - </plugin-configuration> - - </service> - </server> + class="BaseResourceComponent" />
</plugin>
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml index e6ab95f..aeab68f 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<plugin name="ResourceUpgradeMultiTestSibling" +<plugin name="sibling" displayName="Resource Upgrade Multi Test" description="Resource Upgrade Multi Test" package="org.rhq.core.pc.upgrade.plugins.multi.base" @@ -8,34 +8,12 @@ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
- <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> - <depends plugin="ResourceUpgradeMultiTestParentDep"/> + <depends plugin="base" useClasses="true"/>
- <server name="TestResourceParentSibling" - discovery="BaseUpgradingDiscoveryComponent" - class="BaseResourceComponent"> - - <runs-inside> - <parent-resource-type name="ParentDependency" plugin="ResourceUpgradeMultiTestParentDep"/> - </runs-inside> - - <plugin-configuration> - <c:simple-property name="count" default="2" /> - <c:simple-property name="key" default="UPGRADED-test-resource-parent-sibling-%n,parent-%p" /> - </plugin-configuration> - - <service name="TestResourceSibling" - discovery="BaseDiscoveryComponent" - class="BaseResourceComponent"> - <plugin-configuration> - <c:simple-property name="count" default="15" /> - <c:simple-property name="key" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> - </plugin-configuration> - - </service> - - - </server> + <!-- This service is put in the type hierarchy in the v1/v2 test plugins --> + <service name="TestResourceSibling" + discovery="BaseUpgradingDiscoveryComponent" + class="BaseResourceComponent" />
</plugin>
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml index 32ad438..e934494 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?>
-<plugin name="ResourceUpgradeMultiTest" +<plugin name="test" displayName="Resource Upgrade Multi Test" description="Resource Upgrade Multi Test" package="org.rhq.core.pc.upgrade.plugins.multi.base" @@ -9,15 +9,16 @@ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
- <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> - <depends plugin="ResourceUpgradeMultiTestParentDep"/> + <depends plugin="base" useClasses="true"/> + <depends plugin="parentdep"/> + <depends plugin="sibling" />
<server name="TestResourceParent" discovery="BaseDiscoveryComponent" class="BaseResourceComponent">
<runs-inside> - <parent-resource-type name="ParentDependency" plugin="ResourceUpgradeMultiTestParentDep"/> + <parent-resource-type name="ParentDependency" plugin="parentdep"/> </runs-inside>
<plugin-configuration> @@ -29,13 +30,20 @@ <service name="TestResource" discovery="BaseDiscoveryComponent" class="BaseResourceComponent"> - <plugin-configuration> - <c:simple-property name="count" default="10" /> - <c:simple-property name="key" default="test-resource-%n,parent-%p" /> - <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-%n,parent-%p" /> - </plugin-configuration> - - </service> + <plugin-configuration> + <c:simple-property name="count" default="10" /> + <c:simple-property name="key" default="test-resource-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-%n,parent-%p" /> + </plugin-configuration> + </service> + + <service name="TestResourceSibling" sourcePlugin="sibling" sourceType="TestResourceSibling"> + <plugin-configuration> + <c:simple-property name="count" default="10" /> + <c:simple-property name="key" default="test-resource-sibling-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> + </plugin-configuration> + </service> </server>
</plugin> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml index 824d3fe..96658e3 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<plugin name="ResourceUpgradeMultiTest" +<plugin name="test" displayName="Resource Upgrade Multi Test" description="Resource Upgrade Multi Test" package="org.rhq.core.pc.upgrade.plugins.multi.base" @@ -8,15 +8,16 @@ xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
- <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> - <depends plugin="ResourceUpgradeMultiTestParentDep"/> + <depends plugin="base" useClasses="true"/> + <depends plugin="parentdep"/> + <depends plugin="sibling"/>
<server name="TestResourceParent" discovery="BaseUpgradingDiscoveryComponent" class="BaseResourceComponent">
<runs-inside> - <parent-resource-type name="ParentDependency" plugin="ResourceUpgradeMultiTestParentDep"/> + <parent-resource-type name="ParentDependency" plugin="parentdep"/> </runs-inside>
<plugin-configuration> @@ -27,13 +28,19 @@ <service name="TestResource" discovery="BaseDiscoveryComponent" class="BaseResourceComponent"> - <plugin-configuration> - <c:simple-property name="count" default="15" /> - <c:simple-property name="key" default="UPGRADED-test-resource-%n,parent-%p" /> - </plugin-configuration> + <plugin-configuration> + <c:simple-property name="count" default="15" /> <!-- This intentionally differs from v1 --> + <c:simple-property name="key" default="UPGRADED-test-resource-%n,parent-%p" /> + </plugin-configuration>
</service>
+ <service name="TestResourceSibling" sourcePlugin="sibling" sourceType="TestResourceSibling"> + <plugin-configuration> + <c:simple-property name="count" default="15" /> <!-- This intentionally differs from v1 --> + <c:simple-property name="key" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> + </plugin-configuration> + </service>
</server>
commit 097f744dec27c5584cf6203bbaff6fc041753b26 Author: Lukas Krejci lkrejci@redhat.com Date: Wed Sep 29 13:12:09 2010 +0200
Extracted a base class from the upgrade test in preparation for adding another round of tests.
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index 0a2a660..e13ea3d 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -23,43 +23,23 @@
package org.rhq.core.pc.upgrade;
-import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue;
import java.io.File; -import java.io.IOException; -import java.net.URL; import java.util.Collections; import java.util.Set;
-import org.apache.commons.io.FileUtils; import org.jmock.Expectations; import org.jmock.Mockery; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import org.rhq.core.clientapi.server.bundle.BundleServerService; -import org.rhq.core.clientapi.server.configuration.ConfigurationServerService; -import org.rhq.core.clientapi.server.content.ContentServerService; -import org.rhq.core.clientapi.server.core.CoreServerService; -import org.rhq.core.clientapi.server.discovery.DiscoveryServerService; import org.rhq.core.clientapi.server.discovery.InventoryReport; -import org.rhq.core.clientapi.server.event.EventServerService; -import org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService; -import org.rhq.core.clientapi.server.measurement.MeasurementServerService; -import org.rhq.core.clientapi.server.operation.OperationServerService; -import org.rhq.core.domain.discovery.AvailabilityReport; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; -import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.pc.PluginContainer; -import org.rhq.core.pc.PluginContainerConfiguration; -import org.rhq.core.pc.ServerServices; -import org.rhq.core.pc.inventory.InventoryManager; import org.rhq.core.pc.inventory.ResourceContainer; -import org.rhq.core.pc.plugin.FileSystemPluginFinder; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test;
/** * Test cases for resource upgrade. @@ -67,39 +47,14 @@ import org.rhq.core.pc.plugin.FileSystemPluginFinder; * @author Lukas Krejci */ @Test(sequential = true, invocationCount = 1) -public class ResourceUpgradeTest { +public class ResourceUpgradeTest extends ResourceUpgradeTestBase {
private static final String PLUGIN_V1_FILENAME = "/resource-upgrade-test-plugin-1.0.0.jar"; private static final String PLUGIN_V2_FILENAME = "/resource-upgrade-test-plugin-2.0.0.jar"; private static final String FAILING_PLUGIN_FILE_NAME = "/resource-upgrade-test-plugin-3.0.0.jar";
- private static final String PLUGINS_DIR_NAME = "plugins"; - private static final String DATA_DIR_NAME = "data"; - private static final String TMP_DIR_NAME = "tmp"; - - private static final String SINGLETON_RESOURCE_TYPE_NAME = "Resource"; - private static final String SINGLETON_RESOURCE_TYPE_PLUGIN_NAME = "ResourceUpgradeTest"; - - private File tmpDir; - private File pluginDir; - private File dataDir; - - private BundleServerService currentBundleServerService; - private ConfigurationServerService currentConfigurationServerService; - private ContentServerService currentContentServerService; - private CoreServerService currentCoreServerService; - private DiscoveryServerService currentDiscoveryServerService; - private EventServerService currentEventServerService; - private MeasurementServerService currentMeasurementServerService; - private OperationServerService currentOperationServerService; - private ResourceFactoryServerService currentResourceFactoryServerService; - - private FakeServerInventory currentServerSideInventory; - - @AfterClass - public void undeployPlugins() throws IOException { - FileUtils.deleteDirectory(tmpDir); - } + static final String SINGLETON_RESOURCE_TYPE_NAME = "Resource"; + static final String SINGLETON_RESOURCE_TYPE_PLUGIN_NAME = "ResourceUpgradeTest";
@BeforeClass public void sanityCheck() { @@ -108,18 +63,9 @@ public class ResourceUpgradeTest { verifyPluginExists(FAILING_PLUGIN_FILE_NAME); }
- @BeforeClass(dependsOnMethods = "sanityCheck") - public void init() { - tmpDir = getTmpDirectory(); - pluginDir = new File(tmpDir, PLUGINS_DIR_NAME); - assertTrue(pluginDir.mkdir(), "Could not create plugin deploy directory."); - dataDir = new File(tmpDir, DATA_DIR_NAME); - assertTrue(dataDir.mkdir(), "Could not create plugin container data directory."); - } - @Test public void testIgnoreUncommittedResources() throws Exception { - currentServerSideInventory = new FakeServerInventory(); + setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.NEW);
TestPayload testNoChange = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { @@ -138,8 +84,8 @@ public class ResourceUpgradeTest { { defineDefaultExpectations(this);
- between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); - will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED)); } }; } @@ -150,22 +96,22 @@ public class ResourceUpgradeTest {
@Test public void testUpgradeData() throws Exception { - currentServerSideInventory = new FakeServerInventory(); + setCurrentServerSideInventory(new FakeServerInventory()); upgradeTest(false); }
@Test public void testInventoryReinitializationFromServerDuringUpgrade() throws Exception { - currentServerSideInventory = new FakeServerInventory(); + setCurrentServerSideInventory(new FakeServerInventory()); upgradeTest(true); }
@Test public void testSkipUpgradeWhenServerUnavailable() throws Exception { - currentServerSideInventory = new FakeServerInventory(); + setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.COMMITTED);
- currentServerSideInventory.setFailing(true); + getCurrentServerSideInventory().setFailing(true);
TestPayload test = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { public void test(Set<Resource> discoveredResources) { @@ -184,10 +130,10 @@ public class ResourceUpgradeTest { { defineDefaultExpectations(this);
- between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); - will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
- never(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); + never(getCurrentDiscoveryServerService()).upgradeResources(with(any(Set.class))); } }; } @@ -198,7 +144,7 @@ public class ResourceUpgradeTest {
@Test public void testUpgradeWithPlatformDeletedOnServer() throws Exception { - currentServerSideInventory = new FakeServerInventory(); + setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.COMMITTED);
TestPayload test = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { @@ -227,15 +173,15 @@ public class ResourceUpgradeTest {
//the first merge will be triggered from within the upgrade process and we are //going to report null sync. - oneOf(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); - will(currentServerSideInventory.clearPlatform()); + oneOf(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + will(getCurrentServerSideInventory().clearPlatform());
//the rest of the inventory merges are executed by discoveries, so let's import the //discovered stuff into the server-side inventory. - between(1, 3).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); - will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + between(1, 3).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
- never(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); + never(getCurrentDiscoveryServerService()).upgradeResources(with(any(Set.class))); } }; } @@ -246,7 +192,7 @@ public class ResourceUpgradeTest {
@Test public void testUpgradeFailureHandling() throws Exception { - currentServerSideInventory = new FakeServerInventory(); + setCurrentServerSideInventory(new FakeServerInventory()); initialSyncAndDiscovery(InventoryStatus.COMMITTED);
TestPayload test = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { @@ -272,11 +218,11 @@ public class ResourceUpgradeTest { { defineDefaultExpectations(this);
- between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); - will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
- oneOf(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); - will(currentServerSideInventory.upgradeResources()); + oneOf(getCurrentDiscoveryServerService()).upgradeResources(with(any(Set.class))); + will(getCurrentServerSideInventory().upgradeResources()); } }; } @@ -297,20 +243,21 @@ public class ResourceUpgradeTest { assertEquals(discoveredResource.getName(), "resource-name-v1"); assertEquals(discoveredResource.getDescription(), "resource-description-v1"); } - + public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { defineDefaultExpectations(this);
- between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); - will(currentServerSideInventory.mergeInventoryReport(requiredInventoryStatus)); + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + will(getCurrentServerSideInventory().mergeInventoryReport(requiredInventoryStatus)); } }; } });
} +
private void upgradeTest(boolean clearInventoryDat) throws Exception { initialSyncAndDiscovery(InventoryStatus.COMMITTED); @@ -339,189 +286,14 @@ public class ResourceUpgradeTest { { defineDefaultExpectations(this);
- between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); - will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + between(1, 4).of(getCurrentDiscoveryServerService()).mergeInventoryReport(with(any(InventoryReport.class))); + will(getCurrentServerSideInventory().mergeInventoryReport(InventoryStatus.COMMITTED));
- oneOf(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); - will(currentServerSideInventory.upgradeResources()); + oneOf(getCurrentDiscoveryServerService()).upgradeResources(with(any(Set.class))); + will(getCurrentServerSideInventory().upgradeResources()); } }; } }); } - - private PluginContainerConfiguration createPluginContainerConfiguration(Mockery context) throws Exception { - PluginContainerConfiguration conf = new PluginContainerConfiguration(); - - conf.setPluginDirectory(new File(tmpDir, PLUGINS_DIR_NAME)); - conf.setDataDirectory(new File(tmpDir, DATA_DIR_NAME)); - conf.setTemporaryDirectory(new File(tmpDir, TMP_DIR_NAME)); - conf.setInsideAgent(true); //pc must think it's inside an agent so that it persists the inventory between restarts - conf.setPluginFinder(new FileSystemPluginFinder(conf.getPluginDirectory())); - conf.setCreateResourceClassloaders(false); - - //we're not interested in any scans happening out of our control - conf.setAvailabilityScanInitialDelay(Long.MAX_VALUE); - conf.setConfigurationDiscoveryInitialDelay(Long.MAX_VALUE); - conf.setContentDiscoveryInitialDelay(Long.MAX_VALUE); - conf.setEventSenderInitialDelay(Long.MAX_VALUE); - conf.setMeasurementCollectionInitialDelay(Long.MAX_VALUE); - conf.setServerDiscoveryInitialDelay(Long.MAX_VALUE); - conf.setServiceDiscoveryInitialDelay(Long.MAX_VALUE); - - currentBundleServerService = context.mock(BundleServerService.class); - currentConfigurationServerService = context.mock(ConfigurationServerService.class); - currentContentServerService = context.mock(ContentServerService.class); - currentCoreServerService = context.mock(CoreServerService.class); - currentDiscoveryServerService = context.mock(DiscoveryServerService.class); - currentEventServerService = context.mock(EventServerService.class); - currentMeasurementServerService = context.mock(MeasurementServerService.class); - currentOperationServerService = context.mock(OperationServerService.class); - currentResourceFactoryServerService = context.mock(ResourceFactoryServerService.class); - - ServerServices serverServices = new ServerServices(); - serverServices.setBundleServerService(currentBundleServerService); - serverServices.setConfigurationServerService(currentConfigurationServerService); - serverServices.setContentServerService(currentContentServerService); - serverServices.setCoreServerService(currentCoreServerService); - serverServices.setDiscoveryServerService(currentDiscoveryServerService); - serverServices.setEventServerService(currentEventServerService); - serverServices.setMeasurementServerService(currentMeasurementServerService); - serverServices.setOperationServerService(currentOperationServerService); - serverServices.setResourceFactoryServerService(currentResourceFactoryServerService); - - conf.setServerServices(serverServices); - - return conf; - } - - /** - * @param pluginResourcePath - */ - private void verifyPluginExists(String pluginResourcePath) { - URL url = getClass().getResource(pluginResourcePath); - - File pluginFile = FileUtils.toFile(url); - - assertTrue(pluginFile.exists(), pluginFile.getAbsoluteFile() + " plugin jar could not be found."); - } - - private void copyPlugin(String pluginResourcePath, File pluginDirectory) throws IOException { - URL pluginUrl = getClass().getResource(pluginResourcePath); - - File pluginFile = new File(pluginResourcePath); - String pluginFileName = pluginFile.getName(); - - FileUtils.copyURLToFile(pluginUrl, new File(pluginDirectory, pluginFileName)); - } - - private static File getTmpDirectory() { - File ret = new File(System.getProperty("java.io.tmpdir"), "resource-upgrade-test" + System.currentTimeMillis()); - - while (ret.exists() || !ret.mkdir()) { - ret = new File(System.getProperty("java.io.tmpdir"), "resource-upgrade-test" + System.currentTimeMillis()); - } - - return ret; - } - - private interface TestPayload { - Expectations getExpectations(Mockery context) throws Exception; - void test(Set<Resource> resourceUpgradeTestResources); - boolean isClearInventoryDat(); - String getResourceTypeName(); - String getResourceTypePluginName(); - } - - private static abstract class AbstractTestPayload implements TestPayload { - private boolean clearInventoryDat; - private String resourceTypeName; - private String resourceTypePluginName; - - public AbstractTestPayload(boolean clearInventoryDat, String resourceTypeName, String resourceTypePluginName) { - this.clearInventoryDat = clearInventoryDat; - this.resourceTypeName = resourceTypeName; - this.resourceTypePluginName = resourceTypePluginName; - } - - public boolean isClearInventoryDat() { - return clearInventoryDat; - } - - public String getResourceTypeName() { - return resourceTypeName; - } - - public String getResourceTypePluginName() { - return resourceTypePluginName; - } - } - - private Set<Resource> getTestingResources(String resourceTypeName, String resourceTypePluginName) { - ResourceType resType = PluginContainer.getInstance().getPluginManager().getMetadataManager().getType(resourceTypeName, resourceTypePluginName); - - return currentServerSideInventory.findResourcesByType(resType); - } - - private void executeTestWithPlugins(Set<String> pluginResourcePaths, TestPayload test) throws Exception { - FileUtils.cleanDirectory(new File(tmpDir, PLUGINS_DIR_NAME)); - - for(String pluginResourcePath : pluginResourcePaths) { - copyPlugin(pluginResourcePath, pluginDir); - } - - Mockery context = new Mockery(); - - PluginContainerConfiguration pcConfig = createPluginContainerConfiguration(context); - - if (test.isClearInventoryDat()) { - File inventoryDat = new File(pcConfig.getDataDirectory(), "inventory.dat"); - inventoryDat.delete(); - } - - context.checking(test.getExpectations(context)); - - PluginContainer.getInstance().setConfiguration(pcConfig); - PluginContainer.getInstance().initialize(); - - try { - //give the pc the time to finish resource upgrade - Thread.sleep(1000); - - //execute full discovery - InventoryManager im = PluginContainer.getInstance().getInventoryManager(); - im.executeServerScanImmediately(); - im.executeServiceScanImmediately(); - - Set<Resource> resources = getTestingResources(test.getResourceTypeName(), test.getResourceTypePluginName()); - - test.test(resources); - - context.assertIsSatisfied(); - } finally { - PluginContainer.getInstance().shutdown(); - } - } - - @SuppressWarnings("unchecked") - private void defineDefaultExpectations(Expectations expectations) { - expectations.ignoring(currentBundleServerService); - expectations.ignoring(currentConfigurationServerService); - expectations.ignoring(currentContentServerService); - expectations.ignoring(currentCoreServerService); - expectations.ignoring(currentEventServerService); - expectations.ignoring(currentMeasurementServerService); - expectations.ignoring(currentOperationServerService); - expectations.ignoring(currentResourceFactoryServerService); - - //just ignore these invocations if we get a availability scan in the PC... - expectations.allowing(currentDiscoveryServerService).mergeAvailabilityReport(expectations.with(Expectations.any(AvailabilityReport.class))); - - expectations.allowing(currentDiscoveryServerService).getResources(expectations.with(Expectations.any(Set.class)), expectations.with(Expectations.any(boolean.class))); - expectations.will(currentServerSideInventory.getResources()); - } - - private void cleanDataDir() throws IOException { - FileUtils.cleanDirectory(new File(tmpDir, DATA_DIR_NAME)); - } } diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java new file mode 100644 index 0000000..f03f2a4 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTestBase.java @@ -0,0 +1,350 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade; + +import static org.testng.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Set; + +import org.apache.commons.io.FileUtils; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.rhq.core.clientapi.server.bundle.BundleServerService; +import org.rhq.core.clientapi.server.configuration.ConfigurationServerService; +import org.rhq.core.clientapi.server.content.ContentServerService; +import org.rhq.core.clientapi.server.core.CoreServerService; +import org.rhq.core.clientapi.server.discovery.DiscoveryServerService; +import org.rhq.core.clientapi.server.event.EventServerService; +import org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService; +import org.rhq.core.clientapi.server.measurement.MeasurementServerService; +import org.rhq.core.clientapi.server.operation.OperationServerService; +import org.rhq.core.domain.discovery.AvailabilityReport; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.pc.PluginContainer; +import org.rhq.core.pc.PluginContainerConfiguration; +import org.rhq.core.pc.ServerServices; +import org.rhq.core.pc.inventory.InventoryManager; +import org.rhq.core.pc.plugin.FileSystemPluginFinder; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; + +/** + * + * @author Lukas Krejci + */ +public class ResourceUpgradeTestBase { + + private static final String PLUGINS_DIR_NAME = "plugins"; + private static final String DATA_DIR_NAME = "data"; + private static final String TMP_DIR_NAME = "tmp"; + private File tmpDir; + private File pluginDir; + private File dataDir; + private BundleServerService currentBundleServerService; + private ConfigurationServerService currentConfigurationServerService; + private ContentServerService currentContentServerService; + private CoreServerService currentCoreServerService; + private DiscoveryServerService currentDiscoveryServerService; + private EventServerService currentEventServerService; + private MeasurementServerService currentMeasurementServerService; + private OperationServerService currentOperationServerService; + private ResourceFactoryServerService currentResourceFactoryServerService; + private FakeServerInventory currentServerSideInventory; + + @BeforeClass + public void init() { + tmpDir = getTmpDirectory(); + pluginDir = new File(tmpDir, PLUGINS_DIR_NAME); + assertTrue(pluginDir.mkdir(), "Could not create plugin deploy directory."); + dataDir = new File(tmpDir, DATA_DIR_NAME); + assertTrue(dataDir.mkdir(), "Could not create plugin container data directory."); + } + + @AfterClass + public void undeployPlugins() throws IOException { + FileUtils.deleteDirectory(tmpDir); + } + + protected void setCurrentServerSideInventory(FakeServerInventory currentServerSideInventory) { + this.currentServerSideInventory = currentServerSideInventory; + } + + protected FakeServerInventory getCurrentServerSideInventory() { + return currentServerSideInventory; + } + + protected void setCurrentResourceFactoryServerService(ResourceFactoryServerService currentResourceFactoryServerService) { + this.currentResourceFactoryServerService = currentResourceFactoryServerService; + } + + protected ResourceFactoryServerService getCurrentResourceFactoryServerService() { + return currentResourceFactoryServerService; + } + + protected void setCurrentOperationServerService(OperationServerService currentOperationServerService) { + this.currentOperationServerService = currentOperationServerService; + } + + protected OperationServerService getCurrentOperationServerService() { + return currentOperationServerService; + } + + protected void setCurrentMeasurementServerService(MeasurementServerService currentMeasurementServerService) { + this.currentMeasurementServerService = currentMeasurementServerService; + } + + protected MeasurementServerService getCurrentMeasurementServerService() { + return currentMeasurementServerService; + } + + protected void setCurrentEventServerService(EventServerService currentEventServerService) { + this.currentEventServerService = currentEventServerService; + } + + protected EventServerService getCurrentEventServerService() { + return currentEventServerService; + } + + protected void setCurrentDiscoveryServerService(DiscoveryServerService currentDiscoveryServerService) { + this.currentDiscoveryServerService = currentDiscoveryServerService; + } + + protected DiscoveryServerService getCurrentDiscoveryServerService() { + return currentDiscoveryServerService; + } + + protected void setCurrentCoreServerService(CoreServerService currentCoreServerService) { + this.currentCoreServerService = currentCoreServerService; + } + + protected CoreServerService getCurrentCoreServerService() { + return currentCoreServerService; + } + + protected void setCurrentContentServerService(ContentServerService currentContentServerService) { + this.currentContentServerService = currentContentServerService; + } + + protected ContentServerService getCurrentContentServerService() { + return currentContentServerService; + } + + protected void setCurrentConfigurationServerService(ConfigurationServerService currentConfigurationServerService) { + this.currentConfigurationServerService = currentConfigurationServerService; + } + + protected ConfigurationServerService getCurrentConfigurationServerService() { + return currentConfigurationServerService; + } + + protected void setCurrentBundleServerService(BundleServerService currentBundleServerService) { + this.currentBundleServerService = currentBundleServerService; + } + + protected BundleServerService getCurrentBundleServerService() { + return currentBundleServerService; + } + + protected static File getTmpDirectory() { + File ret = new File(System.getProperty("java.io.tmpdir"), "resource-upgrade-test" + System.currentTimeMillis()); + + while (ret.exists() || !ret.mkdir()) { + ret = new File(System.getProperty("java.io.tmpdir"), "resource-upgrade-test" + System.currentTimeMillis()); + } + + return ret; + } + + private PluginContainerConfiguration createPluginContainerConfiguration(Mockery context) throws Exception { + PluginContainerConfiguration conf = new PluginContainerConfiguration(); + + conf.setPluginDirectory(new File(tmpDir, PLUGINS_DIR_NAME)); + conf.setDataDirectory(new File(tmpDir, DATA_DIR_NAME)); + conf.setTemporaryDirectory(new File(tmpDir, TMP_DIR_NAME)); + conf.setInsideAgent(true); //pc must think it's inside an agent so that it persists the inventory between restarts + conf.setPluginFinder(new FileSystemPluginFinder(conf.getPluginDirectory())); + conf.setCreateResourceClassloaders(false); + + //we're not interested in any scans happening out of our control + conf.setAvailabilityScanInitialDelay(Long.MAX_VALUE); + conf.setConfigurationDiscoveryInitialDelay(Long.MAX_VALUE); + conf.setContentDiscoveryInitialDelay(Long.MAX_VALUE); + conf.setEventSenderInitialDelay(Long.MAX_VALUE); + conf.setMeasurementCollectionInitialDelay(Long.MAX_VALUE); + conf.setServerDiscoveryInitialDelay(Long.MAX_VALUE); + conf.setServiceDiscoveryInitialDelay(Long.MAX_VALUE); + + setCurrentBundleServerService(context.mock(BundleServerService.class)); + setCurrentConfigurationServerService(context.mock(ConfigurationServerService.class)); + setCurrentContentServerService(context.mock(ContentServerService.class)); + setCurrentCoreServerService(context.mock(CoreServerService.class)); + setCurrentDiscoveryServerService(context.mock(DiscoveryServerService.class)); + setCurrentEventServerService(context.mock(EventServerService.class)); + setCurrentMeasurementServerService(context.mock(MeasurementServerService.class)); + setCurrentOperationServerService(context.mock(OperationServerService.class)); + setCurrentResourceFactoryServerService(context.mock(ResourceFactoryServerService.class)); + + ServerServices serverServices = new ServerServices(); + serverServices.setBundleServerService(getCurrentBundleServerService()); + serverServices.setConfigurationServerService(getCurrentConfigurationServerService()); + serverServices.setContentServerService(getCurrentContentServerService()); + serverServices.setCoreServerService(getCurrentCoreServerService()); + serverServices.setDiscoveryServerService(getCurrentDiscoveryServerService()); + serverServices.setEventServerService(getCurrentEventServerService()); + serverServices.setMeasurementServerService(getCurrentMeasurementServerService()); + serverServices.setOperationServerService(getCurrentOperationServerService()); + serverServices.setResourceFactoryServerService(getCurrentResourceFactoryServerService()); + + conf.setServerServices(serverServices); + + return conf; + } + + /** + * @param pluginResourcePath + */ + protected void verifyPluginExists(String pluginResourcePath) { + URL url = getClass().getResource(pluginResourcePath); + + File pluginFile = FileUtils.toFile(url); + + assertTrue(pluginFile.exists(), pluginFile.getAbsoluteFile() + " plugin jar could not be found."); + } + + private void copyPlugin(String pluginResourcePath, File pluginDirectory) throws IOException { + URL pluginUrl = getClass().getResource(pluginResourcePath); + + File pluginFile = new File(pluginResourcePath); + String pluginFileName = pluginFile.getName(); + + FileUtils.copyURLToFile(pluginUrl, new File(pluginDirectory, pluginFileName)); + } + + protected interface TestPayload { + Expectations getExpectations(Mockery context) throws Exception; + void test(Set<Resource> resourceUpgradeTestResources); + boolean isClearInventoryDat(); + String getResourceTypeName(); + String getResourceTypePluginName(); + } + + protected static abstract class AbstractTestPayload implements TestPayload { + private boolean clearInventoryDat; + private String resourceTypeName; + private String resourceTypePluginName; + + public AbstractTestPayload(boolean clearInventoryDat, String resourceTypeName, String resourceTypePluginName) { + this.clearInventoryDat = clearInventoryDat; + this.resourceTypeName = resourceTypeName; + this.resourceTypePluginName = resourceTypePluginName; + } + + public boolean isClearInventoryDat() { + return clearInventoryDat; + } + + public String getResourceTypeName() { + return resourceTypeName; + } + + public String getResourceTypePluginName() { + return resourceTypePluginName; + } + } + + /** + * + */ + public ResourceUpgradeTestBase() { + super(); + } + + private Set<Resource> getTestingResources(String resourceTypeName, String resourceTypePluginName) { + ResourceType resType = PluginContainer.getInstance().getPluginManager().getMetadataManager().getType(resourceTypeName, resourceTypePluginName); + + return getCurrentServerSideInventory().findResourcesByType(resType); + } + + protected void executeTestWithPlugins(Set<String> pluginResourcePaths, TestPayload test) throws Exception { + FileUtils.cleanDirectory(new File(tmpDir, PLUGINS_DIR_NAME)); + + for(String pluginResourcePath : pluginResourcePaths) { + copyPlugin(pluginResourcePath, pluginDir); + } + + Mockery context = new Mockery(); + + PluginContainerConfiguration pcConfig = createPluginContainerConfiguration(context); + + if (test.isClearInventoryDat()) { + File inventoryDat = new File(pcConfig.getDataDirectory(), "inventory.dat"); + inventoryDat.delete(); + } + + context.checking(test.getExpectations(context)); + + PluginContainer.getInstance().setConfiguration(pcConfig); + PluginContainer.getInstance().initialize(); + + try { + //give the pc the time to finish resource upgrade + Thread.sleep(1000); + + //execute full discovery + InventoryManager im = PluginContainer.getInstance().getInventoryManager(); + im.executeServerScanImmediately(); + im.executeServiceScanImmediately(); + + Set<Resource> resources = getTestingResources(test.getResourceTypeName(), test.getResourceTypePluginName()); + + test.test(resources); + + context.assertIsSatisfied(); + } finally { + PluginContainer.getInstance().shutdown(); + } + } + + @SuppressWarnings("unchecked") + protected void defineDefaultExpectations(Expectations expectations) { + expectations.ignoring(getCurrentBundleServerService()); + expectations.ignoring(getCurrentConfigurationServerService()); + expectations.ignoring(getCurrentContentServerService()); + expectations.ignoring(getCurrentCoreServerService()); + expectations.ignoring(getCurrentEventServerService()); + expectations.ignoring(getCurrentMeasurementServerService()); + expectations.ignoring(getCurrentOperationServerService()); + expectations.ignoring(getCurrentResourceFactoryServerService()); + + //just ignore these invocations if we get a availability scan in the PC... + expectations.allowing(getCurrentDiscoveryServerService()).mergeAvailabilityReport(expectations.with(Expectations.any(AvailabilityReport.class))); + + expectations.allowing(getCurrentDiscoveryServerService()).getResources(expectations.with(Expectations.any(Set.class)), expectations.with(Expectations.any(boolean.class))); + expectations.will(getCurrentServerSideInventory().getResources()); + } + + protected void cleanDataDir() throws IOException { + FileUtils.cleanDirectory(new File(tmpDir, DATA_DIR_NAME)); + } +}
commit 1863f1ab0c4473e6a79c469c16b73b6810733325 Author: Lukas Krejci lkrejci@redhat.com Date: Wed Sep 29 12:58:32 2010 +0200
Preparing the upgrade tests to accept more complicated scenarios.
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index 1479345..0a2a660 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -77,6 +77,9 @@ public class ResourceUpgradeTest { private static final String DATA_DIR_NAME = "data"; private static final String TMP_DIR_NAME = "tmp";
+ private static final String SINGLETON_RESOURCE_TYPE_NAME = "Resource"; + private static final String SINGLETON_RESOURCE_TYPE_PLUGIN_NAME = "ResourceUpgradeTest"; + private File tmpDir; private File pluginDir; private File dataDir; @@ -119,8 +122,12 @@ public class ResourceUpgradeTest { currentServerSideInventory = new FakeServerInventory(); initialSyncAndDiscovery(InventoryStatus.NEW);
- TestPayload testNoChange = new TestPayload() { - public void test(Resource discoveredResource) { + TestPayload testNoChange = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { + public void test(Set<Resource> discoveredResources) { + assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); + + Resource discoveredResource = discoveredResources.iterator().next(); + assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); assertEquals(discoveredResource.getName(), "resource-name-v1"); assertEquals(discoveredResource.getDescription(), "resource-description-v1"); @@ -138,7 +145,7 @@ public class ResourceUpgradeTest { } };
- executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, testNoChange); + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), testNoChange); }
@Test @@ -160,8 +167,12 @@ public class ResourceUpgradeTest {
currentServerSideInventory.setFailing(true);
- TestPayload test = new TestPayload() { - public void test(Resource discoveredResource) { + TestPayload test = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { + public void test(Set<Resource> discoveredResources) { + assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); + + Resource discoveredResource = discoveredResources.iterator().next(); + assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); assertEquals(discoveredResource.getName(), "resource-name-v1"); assertEquals(discoveredResource.getDescription(), "resource-description-v1"); @@ -182,7 +193,7 @@ public class ResourceUpgradeTest { } };
- executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, test); + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), test); }
@Test @@ -190,8 +201,12 @@ public class ResourceUpgradeTest { currentServerSideInventory = new FakeServerInventory(); initialSyncAndDiscovery(InventoryStatus.COMMITTED);
- TestPayload test = new TestPayload() { - public void test(Resource discoveredResource) { + TestPayload test = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { + public void test(Set<Resource> discoveredResources) { + assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); + + Resource discoveredResource = discoveredResources.iterator().next(); + assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); assertEquals(discoveredResource.getName(), "resource-name-v2"); assertEquals(discoveredResource.getDescription(), "resource-description-v2"); @@ -226,7 +241,7 @@ public class ResourceUpgradeTest { } };
- executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, test); + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), test); }
@Test @@ -234,12 +249,16 @@ public class ResourceUpgradeTest { currentServerSideInventory = new FakeServerInventory(); initialSyncAndDiscovery(InventoryStatus.COMMITTED);
- TestPayload test = new TestPayload() { - public void test(Resource resourceUpgradeTestResource) { - assertTrue(resourceUpgradeTestResource.getResourceErrors().size() > 0, "There should be upgrade errors persisted on the server side."); + TestPayload test = new AbstractTestPayload(false, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { + public void test(Set<Resource> resourceUpgradeTestResources) { + assertEquals(resourceUpgradeTestResources.size(), 1, "Expected single test resource but multiple found."); + + Resource discoveredResource = resourceUpgradeTestResources.iterator().next(); + + assertTrue(discoveredResource.getResourceErrors().size() > 0, "There should be upgrade errors persisted on the server side.");
//the discovery of the failed resource mustn't have run - ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(resourceUpgradeTestResource); + ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(discoveredResource); File dataDir = container.getResourceContext().getDataDirectory();
File marker = new File(dataDir, "failing-discovery-ran"); @@ -263,13 +282,17 @@ public class ResourceUpgradeTest { } };
- executeTestWithPlugins(Collections.singleton(FAILING_PLUGIN_FILE_NAME), false, test); + executeTestWithPlugins(Collections.singleton(FAILING_PLUGIN_FILE_NAME), test); }
private void initialSyncAndDiscovery(final InventoryStatus requiredInventoryStatus) throws Exception { cleanDataDir(); - executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), true, new TestPayload() { - public void test(Resource discoveredResource) { + executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), new AbstractTestPayload(true, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { + public void test(Set<Resource> discoveredResources) { + assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); + + Resource discoveredResource = discoveredResources.iterator().next(); + assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); assertEquals(discoveredResource.getName(), "resource-name-v1"); assertEquals(discoveredResource.getDescription(), "resource-description-v1"); @@ -292,8 +315,12 @@ public class ResourceUpgradeTest { private void upgradeTest(boolean clearInventoryDat) throws Exception { initialSyncAndDiscovery(InventoryStatus.COMMITTED);
- executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), clearInventoryDat, new TestPayload() { - public void test(Resource discoveredResource) { + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), new AbstractTestPayload(clearInventoryDat, SINGLETON_RESOURCE_TYPE_NAME, SINGLETON_RESOURCE_TYPE_PLUGIN_NAME) { + public void test(Set<Resource> discoveredResources) { + assertEquals(discoveredResources.size(), 1, "Expected single test resource but multiple found."); + + Resource discoveredResource = discoveredResources.iterator().next(); + assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); assertEquals(discoveredResource.getName(), "resource-name-v2"); assertEquals(discoveredResource.getDescription(), "resource-description-v2"); @@ -400,16 +427,43 @@ public class ResourceUpgradeTest {
private interface TestPayload { Expectations getExpectations(Mockery context) throws Exception; - void test(Resource resourceUpgradeTestResource); + void test(Set<Resource> resourceUpgradeTestResources); + boolean isClearInventoryDat(); + String getResourceTypeName(); + String getResourceTypePluginName(); }
- private Set<Resource> getTestingResources() { - ResourceType resType = PluginContainer.getInstance().getPluginManager().getMetadataManager().getType("Resource", "ResourceUpgradeTest"); + private static abstract class AbstractTestPayload implements TestPayload { + private boolean clearInventoryDat; + private String resourceTypeName; + private String resourceTypePluginName; + + public AbstractTestPayload(boolean clearInventoryDat, String resourceTypeName, String resourceTypePluginName) { + this.clearInventoryDat = clearInventoryDat; + this.resourceTypeName = resourceTypeName; + this.resourceTypePluginName = resourceTypePluginName; + } + + public boolean isClearInventoryDat() { + return clearInventoryDat; + } + + public String getResourceTypeName() { + return resourceTypeName; + } + + public String getResourceTypePluginName() { + return resourceTypePluginName; + } + } + + private Set<Resource> getTestingResources(String resourceTypeName, String resourceTypePluginName) { + ResourceType resType = PluginContainer.getInstance().getPluginManager().getMetadataManager().getType(resourceTypeName, resourceTypePluginName);
return currentServerSideInventory.findResourcesByType(resType); }
- private void executeTestWithPlugins(Set<String> pluginResourcePaths, boolean clearInventoryDat, TestPayload test) throws Exception { + private void executeTestWithPlugins(Set<String> pluginResourcePaths, TestPayload test) throws Exception { FileUtils.cleanDirectory(new File(tmpDir, PLUGINS_DIR_NAME));
for(String pluginResourcePath : pluginResourcePaths) { @@ -420,7 +474,7 @@ public class ResourceUpgradeTest {
PluginContainerConfiguration pcConfig = createPluginContainerConfiguration(context);
- if (clearInventoryDat) { + if (test.isClearInventoryDat()) { File inventoryDat = new File(pcConfig.getDataDirectory(), "inventory.dat"); inventoryDat.delete(); } @@ -439,14 +493,9 @@ public class ResourceUpgradeTest { im.executeServerScanImmediately(); im.executeServiceScanImmediately();
- Set<Resource> resources = getTestingResources(); - - assertEquals(resources.size(), 1, "There should be only a single testing resource but " + resources - + " were found."); - - Resource discoveredResource = resources.iterator().next(); + Set<Resource> resources = getTestingResources(test.getResourceTypeName(), test.getResourceTypePluginName());
- test.test(discoveredResource); + test.test(resources);
context.assertIsSatisfied(); } finally {
commit 659920513807b095cdd0ac91c3f1c2e091d090a7 Author: Lukas Krejci lkrejci@redhat.com Date: Wed Sep 29 12:57:21 2010 +0200
Setting the height of the errorsGrid to a fixed value so that it stays at the bottom of the page.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java index 95bec5f..b439d44 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java @@ -23,11 +23,7 @@ import org.rhq.core.domain.resource.composite.ResourceComposite; import org.rhq.enterprise.gui.coregui.client.components.table.Table; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
-import com.smartgwt.client.data.DSCallback; -import com.smartgwt.client.data.DSRequest; -import com.smartgwt.client.data.DSResponse; import com.smartgwt.client.types.Alignment; -import com.smartgwt.client.types.GroupStartOpen; import com.smartgwt.client.widgets.HTMLPane; import com.smartgwt.client.widgets.IButton; import com.smartgwt.client.widgets.Window; @@ -44,13 +40,11 @@ import com.smartgwt.client.widgets.grid.events.CellClickHandler; */ public class OverviewView extends LocatableVLayout {
- private ResourceComposite resourceComposite; private OverviewForm form; private Table errorsGrid;
public OverviewView(String locatorId, ResourceComposite resourceComposite) { super(locatorId); - this.resourceComposite = resourceComposite; form = new OverviewForm(extendLocatorId("form"), resourceComposite); errorsGrid = new Table(extendLocatorId("errors"), "Detected errors", null, null, new String[] { ResourceErrorsDataSource.DETAIL_ID });
@@ -61,7 +55,7 @@ public class OverviewView extends LocatableVLayout { errorsGrid.setDataSource(errors);
form.setHeight("*"); - errorsGrid.setHeight("10%"); + errorsGrid.setHeight(200); //this should be just enough to fit the maximum of 3 rows in this table (there's at most 1 error per type)
addMember(form); addMember(errorsGrid);
commit c704c79f4acfedf4d959de6d7d27db1b22efa1f3 Author: Lukas Krejci lkrejci@redhat.com Date: Wed Sep 29 12:44:55 2010 +0200
Adding a bunch of test plugins for dependency resolution during resource upgrade failure handling.
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml index 4b09ef8..035bf36 100644 --- a/modules/core/plugin-container/pom.xml +++ b/modules/core/plugin-container/pom.xml @@ -195,6 +195,106 @@ <fileset dir="${project.build.testOutputDirectory}/tmp/failing" includes="**/*.class,**/rhq-plugin.xml" /> </jar>
+ <copy toDir="${project.build.testOutputDirectory}/tmp/multi/base/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/base/rhq-plugin.xml" /> + </copy> + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/base/org/rhq/core/pc/upgrade/plugins/multi/base"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/base/*.class" /> + </copy> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-base-1.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/base" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/parentdep1/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/rhq-plugin.xml" /> + </copy> + <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/parentdep1/org/rhq/core/pc/upgrade/plugins/multi/parentdep1"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/*.class" /> + </copy> --> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-parentdep-1.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/parentdep1" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/parentdep2/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/rhq-plugin.xml" /> + </copy> + <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/parentdep2/org/rhq/core/pc/upgrade/plugins/multi/parentdep2"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/*.class" /> + </copy> --> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-parentdep-2.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/parentdep2" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/parentsibling1/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml" /> + </copy> + <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/parentsibling1/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/*.class" /> + </copy> --> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-parentsibling-1.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/parentsibling1" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/parentsibling2/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml" /> + </copy> + <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/parentsibling2/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/*.class" /> + </copy> --> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-parentsibling-2.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/parentsibling2" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/root/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/root/rhq-plugin.xml" /> + </copy> + <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/root/org/rhq/core/pc/upgrade/plugins/multi/root"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/root/*.class" /> + </copy> --> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-root-1.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/root" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/sibling1/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml" /> + </copy> + <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/sibling1/org/rhq/core/pc/upgrade/plugins/multi/sibling1"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/sibling1/*.class" /> + </copy> --> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-sibling-1.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/sibling1" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/sibling2/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml" /> + </copy> + <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/sibling2/org/rhq/core/pc/upgrade/plugins/multi/sibling2"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/sibling2/*.class" /> + </copy> --> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-sibling-2.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/sibling2" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/v1/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml" /> + </copy> + <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/v1/org/rhq/core/pc/upgrade/plugins/multi/v1"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/v1/*.class" /> + </copy> --> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-1.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/v1" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + + <copy toDir="${project.build.testOutputDirectory}/tmp/multi/v2/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml" /> + </copy> + <!-- <copy toDir="${project.build.testOutputDirectory}/tmp/multi/v2/org/rhq/core/pc/upgrade/plugins/multi/v2"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/multi/v2/*.class" /> + </copy> --> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-multi-2.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/multi/v2" includes="**/*.class,**/rhq-plugin.xml" /> + </jar> + <delete dir="${project.build.testOutputDirectory}/tmp"/> </tasks> </configuration> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseDiscoveryComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseDiscoveryComponent.java new file mode 100644 index 0000000..61d4fe0 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseDiscoveryComponent.java @@ -0,0 +1,70 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade.plugins.multi.base; + +import java.util.HashSet; +import java.util.Set; + +import org.rhq.core.domain.configuration.Configuration; +import org.rhq.core.domain.configuration.PropertySimple; +import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails; +import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; + +/** + * + * @author Lukas Krejci + */ +public class BaseDiscoveryComponent<T extends ResourceComponent> implements ResourceDiscoveryComponent<T> { + + public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<T> context) + throws InvalidPluginConfigurationException, Exception { + + HashSet<DiscoveredResourceDetails> results = new HashSet<DiscoveredResourceDetails>(); + + Configuration pluginConfig = context.getDefaultPluginConfiguration(); + + String keyTemplate = pluginConfig.getSimpleValue("key", null); + int count = pluginConfig.getSimple("count").getIntegerValue(); + + int parentN = context.getParentResourceContext().getPluginConfiguration().getSimple("ordinal") + .getIntegerValue(); + + for (int i = 0; i < count; ++i) { + + String key = getResourceKey(keyTemplate, i, parentN); + + pluginConfig.put(new PropertySimple("ordinal", i)); + + DiscoveredResourceDetails detail = new DiscoveredResourceDetails(context.getResourceType(), key, key, null, + null, pluginConfig, null); + + results.add(detail); + } + + return results; + } + + protected static String getResourceKey(String template, int n, int parentN) { + return template.replace("%n", Integer.toString(n)).replace("%p", Integer.toString(parentN)); + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponent.java new file mode 100644 index 0000000..c5bbf3a --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseResourceComponent.java @@ -0,0 +1,67 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade.plugins.multi.base; + +import java.util.Collections; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.rhq.core.domain.measurement.AvailabilityType; +import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceContext; + +/** + * + * @author Lukas Krejci + */ +public class BaseResourceComponent<T extends ResourceComponent> implements ResourceComponent<T> { + + private ResourceContext<T> context; + private final Log log = LogFactory.getLog(getClass()); + + private Set<Integer> childrenToFailUpgrade; + + public AvailabilityType getAvailability() { + return AvailabilityType.UP; + } + + public void start(ResourceContext<T> context) throws InvalidPluginConfigurationException, Exception { + log.info("Starting multi resource child component with resource key '" + context.getResourceKey() + "'."); + this.context = context; + } + + public void stop() { + log.info("Stopping multi resource child component with resource key '" + context.getResourceKey() + "'."); + } + + public int getOrdinal() { + return context.getPluginConfiguration().getSimple("ordinal").getIntegerValue(); + } + + public Set<Integer> getChildrenToFailUpgrade() { + return childrenToFailUpgrade == null ? Collections.<Integer>emptySet() : childrenToFailUpgrade; + } + + public void setChildrenToFailUpgrade(Set<Integer> childrenToFailUpgrade) { + this.childrenToFailUpgrade = childrenToFailUpgrade; + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java new file mode 100644 index 0000000..beb36db --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/BaseUpgradingDiscoveryComponent.java @@ -0,0 +1,61 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade.plugins.multi.base; + +import org.rhq.core.domain.configuration.Configuration; +import org.rhq.core.domain.resource.ResourceUpgradeReport; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; + +/** + * + * @author Lukas Krejci + */ +public class BaseUpgradingDiscoveryComponent<T extends BaseResourceComponent> extends BaseDiscoveryComponent<T> implements ResourceUpgradeFacet<T> { + + public ResourceUpgradeReport upgrade(ResourceUpgradeContext<T> inventoriedResource) { + Configuration pluginConfig = inventoriedResource.getPluginConfiguration(); + + BaseResourceComponent<?> parent = inventoriedResource.getParentResourceComponent(); + int ordinal = pluginConfig.getSimple("ordinal").getIntegerValue(); + int parentOrdinal = parent == null ? 0 : parent.getOrdinal(); + + boolean fail = Boolean.getBoolean(pluginConfig.getSimpleValue("failUpgrade", "false")); + + if (!fail && parent != null) { + fail = parent.getChildrenToFailUpgrade().contains(Integer.valueOf(ordinal)); + } + + if (fail) { + throw new RuntimeException("Failing the resource upgrade purposefully."); + } + + String newKey = pluginConfig.getSimpleValue("upgradedKey", null); + + if (newKey == null) { + return null; + } + + ResourceUpgradeReport report = new ResourceUpgradeReport(); + + report.setNewResourceKey(getResourceKey(newKey, ordinal, parentOrdinal)); + return null; + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/rhq-plugin.xml new file mode 100644 index 0000000..7edfba1 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/base/rhq-plugin.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<plugin name="ResourceUpgradeMultiTestBase" + displayName="" + description="" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <!-- + Only the inheriting plugins create the concrete resources based on the + classes defined in this abstract base plugin. + + These are the plugin configuration properties needed by the base plugin: + + key = the template to create the resource key from + count = the number of resources to discover + upgradedKey = this *must* be specified on the resource type *to be upgraded* and + *must* be the same as the key template on the resource type that + it is upgraded to (i.e. the plugin.v1.upgradedKey == plugin.v2.key) + + the discovery add a new property called "ordinal" to the plugin config + of the created resources, which contains the index of that resource amongst + its siblings. + + the key template can contain %n which is replaced by the ordinal and %p which + is replaced by the ordinal of its parent. + + + + if the discovery component of the concrete resource is (or inherits from) + BaseUpgradingDiscoveryComponent, it can specify further plugin config properties + influencing the upgrade: + + failUpgrade = true to throw an exception during upgrade + --> + +</plugin> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/rhq-plugin.xml new file mode 100644 index 0000000..3612974 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep1/rhq-plugin.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeMultiTestParentDep" + displayName="Resource Upgrade Multi Test" + description="Resource Upgrade Multi Test" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> + <depends plugin="ResourceUpgradeMultiTestRoot"/> + + <server name="ParentDependency" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + + <runs-inside> + <parent-resource-type name="Root" plugin="ResourceUpgradeMultiTestRoot"/> + </runs-inside> + + <plugin-configuration> + <c:simple-property name="count" default="1" /> + <c:simple-property name="key" default="test-resource-parent-dep-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-parent-dep-%n,parent-%p" /> + </plugin-configuration> + + </server> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/rhq-plugin.xml new file mode 100644 index 0000000..6b95114 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentdep2/rhq-plugin.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeMultiTestParentDep" + displayName="Resource Upgrade Multi Test" + description="Resource Upgrade Multi Test" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="2.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> + <depends plugin="ResourceUpgradeMultiTestRoot"/> + + <server name="ParentDependency" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + + <runs-inside> + <parent-resource-type name="Root" plugin="ResourceUpgradeMultiTestRoot"/> + </runs-inside> + + <plugin-configuration> + <c:simple-property name="count" default="1" /> + <c:simple-property name="key" default="UPGRADED-test-resource-parent-dep-%n,parent-%p" /> + </plugin-configuration> + + </server> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml new file mode 100644 index 0000000..fbade54 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling1/rhq-plugin.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeMultiTestParentSibling" + displayName="Resource Upgrade Multi Test" + description="Resource Upgrade Multi Test" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> + <depends plugin="ResourceUpgradeMultiTestRoot"/> + + <server name="ParentDepSibling" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + + <runs-inside> + <parent-resource-type name="Root" plugin="ResourceUpgradeMultiTestRoot"/> + </runs-inside> + + <plugin-configuration> + <c:simple-property name="count" default="1" /> + <c:simple-property name="key" default="test-resource-parent-sibling-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-parent-sibling-%n,parent-%p" /> + </plugin-configuration> + + </server> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml new file mode 100644 index 0000000..f16d526 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/parentsibling2/rhq-plugin.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeMultiTestParentSibling" + displayName="Resource Upgrade Multi Test" + description="Resource Upgrade Multi Test" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="2.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> + <depends plugin="ResourceUpgradeMultiTestRoot"/> + + <server name="ParentDepSibling" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + + <runs-inside> + <parent-resource-type name="Root" plugin="ResourceUpgradeMultiTestRoot"/> + </runs-inside> + + <plugin-configuration> + <c:simple-property name="count" default="1" /> + <c:simple-property name="key" default="UPGRADED-test-resource-parent-sibling-%n,parent-%p" /> + </plugin-configuration> + + </server> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/root/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/root/rhq-plugin.xml new file mode 100644 index 0000000..b5efbb1 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/root/rhq-plugin.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeMultiTestRoot" + displayName="" + description="" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <server name="Root" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + + <plugin-configuration> + <c:simple-property name="count" default="1" /> + <c:simple-property name="key" default="test-resource-root-%n" /> + </plugin-configuration> + </server> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml new file mode 100644 index 0000000..f87ef4d --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling1/rhq-plugin.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeMultiTestSibling" + displayName="Resource Upgrade Multi Test" + description="Resource Upgrade Multi Test" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> + <depends plugin="ResourceUpgradeMultiTestParentDep"/> + + <server name="TestResourceParentSibling" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + + <plugin-configuration> + <c:simple-property name="count" default="2" /> + <c:simple-property name="key" default="test-resource-parent-sibling-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-parent-sibling-%n,parent-%p" /> + </plugin-configuration> + + <service name="TestResourceSibling" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + <plugin-configuration> + <c:simple-property name="count" default="10" /> + <c:simple-property name="key" default="test-resource-sibling-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> + </plugin-configuration> + + </service> + </server> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml new file mode 100644 index 0000000..e6ab95f --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/sibling2/rhq-plugin.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<plugin name="ResourceUpgradeMultiTestSibling" + displayName="Resource Upgrade Multi Test" + description="Resource Upgrade Multi Test" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="2.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> + <depends plugin="ResourceUpgradeMultiTestParentDep"/> + + <server name="TestResourceParentSibling" + discovery="BaseUpgradingDiscoveryComponent" + class="BaseResourceComponent"> + + <runs-inside> + <parent-resource-type name="ParentDependency" plugin="ResourceUpgradeMultiTestParentDep"/> + </runs-inside> + + <plugin-configuration> + <c:simple-property name="count" default="2" /> + <c:simple-property name="key" default="UPGRADED-test-resource-parent-sibling-%n,parent-%p" /> + </plugin-configuration> + + <service name="TestResourceSibling" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + <plugin-configuration> + <c:simple-property name="count" default="15" /> + <c:simple-property name="key" default="UPGRADED-test-resource-sibling-%n,parent-%p" /> + </plugin-configuration> + + </service> + + + </server> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml new file mode 100644 index 0000000..32ad438 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v1/rhq-plugin.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeMultiTest" + displayName="Resource Upgrade Multi Test" + description="Resource Upgrade Multi Test" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> + <depends plugin="ResourceUpgradeMultiTestParentDep"/> + + <server name="TestResourceParent" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + + <runs-inside> + <parent-resource-type name="ParentDependency" plugin="ResourceUpgradeMultiTestParentDep"/> + </runs-inside> + + <plugin-configuration> + <c:simple-property name="count" default="2" /> + <c:simple-property name="key" default="test-resource-parent-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-parent-%n,parent-%p" /> + </plugin-configuration> + + <service name="TestResource" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + <plugin-configuration> + <c:simple-property name="count" default="10" /> + <c:simple-property name="key" default="test-resource-%n,parent-%p" /> + <c:simple-property name="upgradedKey" default="UPGRADED-test-resource-%n,parent-%p" /> + </plugin-configuration> + + </service> + </server> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml new file mode 100644 index 0000000..824d3fe --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/multi/v2/rhq-plugin.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<plugin name="ResourceUpgradeMultiTest" + displayName="Resource Upgrade Multi Test" + description="Resource Upgrade Multi Test" + package="org.rhq.core.pc.upgrade.plugins.multi.base" + version="2.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <depends plugin="ResourceUpgradeMultiTestBase" useClasses="true"/> + <depends plugin="ResourceUpgradeMultiTestParentDep"/> + + <server name="TestResourceParent" + discovery="BaseUpgradingDiscoveryComponent" + class="BaseResourceComponent"> + + <runs-inside> + <parent-resource-type name="ParentDependency" plugin="ResourceUpgradeMultiTestParentDep"/> + </runs-inside> + + <plugin-configuration> + <c:simple-property name="count" default="2" /> + <c:simple-property name="key" default="UPGRADED-test-resource-parent-%n,parent-%p" /> + </plugin-configuration> + + <service name="TestResource" + discovery="BaseDiscoveryComponent" + class="BaseResourceComponent"> + <plugin-configuration> + <c:simple-property name="count" default="15" /> + <c:simple-property name="key" default="UPGRADED-test-resource-%n,parent-%p" /> + </plugin-configuration> + + </service> + + + </server> + +</plugin> +
commit c2f5b5363d1023106bc7e12a78999603c4c5f26e Author: Lukas Krejci lkrejci@redhat.com Date: Tue Sep 28 10:39:33 2010 +0200
remove the commented-out portions of the resource upgrade code.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 1b0ed8e..de52cd8 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -1232,10 +1232,7 @@ public class InventoryManager extends AgentService implements ContainerService, for (ResourceUpgradeResponse upgradeResponse : serverUpdates) { String resourceKey = upgradeResponse.getUpgradedResourceKey(); String name = upgradeResponse.getUpgradedResourceName(); - //String version = upgradeReport.getNewVersion(); String description = upgradeResponse.getUpgradedResourceDescription(); - //Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); - //Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration();
//only bother if there's something to upgrade at all on this resource. if (resourceKey != null || name != null || description != null) { @@ -1256,23 +1253,11 @@ public class InventoryManager extends AgentService implements ContainerService, logMessage.append("name, "); }
- //if (version != null) { - // existingResource.setVersion(version); - //} - if (description != null) { existingResource.setDescription(description); logMessage.append("description, "); }
- //if (pluginConfiguration != null) { - // existingResource.setPluginConfiguration(pluginConfiguration); - //} - // - //if (resourceConfiguration != null) { - // existingResource.setResourceConfiguration(resourceConfiguration); - //} - logMessage.replace(logMessage.length() - 1, logMessage.length(), "to become [").append( existingResource.toString()).append("]");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index 51287b7..e4cbf03 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -495,10 +495,7 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot
String resourceKey = upgradeRequest.getNewResourceKey(); String name = upgradeRequest.getNewName(); -// String version = upgradeReport.getNewVersion(); String description = upgradeRequest.getNewDescription(); -// Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); -// Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration();
if (resourceKey != null || name != null || description != null) { StringBuilder logMessage = new StringBuilder("Resource [") @@ -516,38 +513,12 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot } ret.setUpgradedResourceName(resource.getName());
-// if (version != null) { -// changed = updateResourceVersion(resource, version) || changed; -// } - if (allowGenericPropertiesUpgrade && needsUpgrade(resource.getDescription(), description)) { resource.setDescription(description); logMessage.append("description, "); } ret.setUpgradedResourceDescription(resource.getDescription()); - -// if (pluginConfiguration != null) { -// if (!equalOrNull(pluginConfiguration, resource.getPluginConfiguration())) { -// log.info("Resource [" + resource + "] upgraded its plugin configuration from [" + -// resource.getPluginConfiguration() + "] to [" + pluginConfiguration + "]"); -// changed = true; -// resource.setPluginConfiguration(pluginConfiguration); -// } -// } -// -// if (resourceConfiguration != null) { -// if (!equalOrNull(resourceConfiguration, resource.getResourceConfiguration())) { -// //XXX Will this create a new history entry? -// -// log.info("Resource [" + resource + "] upgraded its resource configuration from [" + -// resource.getResourceConfiguration() + "] to [" + resourceConfiguration + "]"); -// -// changed = true; -// resource.setResourceConfiguration(resourceConfiguration); -// } -// } - - + //finally let's remove the potential previous upgrade error. we've now successfully //upgraded the resource. List<ResourceError> upgradeErrors = resourceManager.findResourceErrors(subjectManager.getOverlord(), resource.getId(), ResourceErrorType.UPGRADE);
commit 0ae5aa90c40d239e294857a961596ee500643dee Author: Lukas Krejci lkrejci@redhat.com Date: Tue Sep 28 10:36:32 2010 +0200
Clear the upgrade errors if the upgrade for given resource succeeds.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index a480fb7..51287b7 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -481,7 +481,7 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot * @param existingResource * @param upgradeRequest * @param allowGenericPropertiesUpgrade name and description are only upgraded if this is true - * @return true if the resource was changed, false otherwise + * @return response to the upgrade request detailing what has been accepted on the server side */ private ResourceUpgradeResponse upgradeResource(@NotNull Resource resource, ResourceUpgradeRequest upgradeRequest, boolean allowGenericPropertiesUpgrade) { if (upgradeRequest.getUpgradeErrorMessage() != null) { @@ -547,6 +547,14 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot // } // }
+ + //finally let's remove the potential previous upgrade error. we've now successfully + //upgraded the resource. + List<ResourceError> upgradeErrors = resourceManager.findResourceErrors(subjectManager.getOverlord(), resource.getId(), ResourceErrorType.UPGRADE); + for(ResourceError error : upgradeErrors) { + entityManager.remove(error); + } + logMessage.replace(logMessage.length() - 1, logMessage.length(), "to become [").append(resource.toString()).append("]");
commit c1b1f4dfdcf05c39879133c9fb562f8ecada6690 Author: Lukas Krejci lkrejci@redhat.com Date: Fri Sep 24 14:32:23 2010 +0200
Handling the resource upgrade failure by disabling discovery of its siblings of the same type.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 563a786..1b0ed8e 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -192,7 +192,7 @@ public class InventoryManager extends AgentService implements ContainerService, /** * Handles the resource upgrade during the initialization of the inventory manager. */ - private ResourceUpgradeDelegate resourceUpgradeDelegate; + private ResourceUpgradeDelegate resourceUpgradeDelegate = new ResourceUpgradeDelegate(this);
public InventoryManager() { super(DiscoveryAgentService.class); @@ -222,7 +222,6 @@ public class InventoryManager extends AgentService implements ContainerService, //try the resource upgrade before we have any schedulers set up //so that we don't get any interventions from concurrently running //discoveries. - resourceUpgradeDelegate = new ResourceUpgradeDelegate(this); upgradeResources();
availabilityCollectors = new AvailabilityCollectorThreadPool(); @@ -282,15 +281,24 @@ public class InventoryManager extends AgentService implements ContainerService, * an empty set if nothing is discovered. This may return <code>null</code> if for some reason * we could not invoke the discovery component. * + * @param parentResourceContainer the container of the resource under which we are going to execute the discovery * @param component the discovery component that will actually go out and discover resources * @param context the context for use by the discovery component * @return the details of all discovered resources, may be empty or <code>null</code> * * @throws Exception if the discovery component threw an exception */ - public Set<DiscoveredResourceDetails> invokeDiscoveryComponent(ResourceDiscoveryComponent component, + public Set<DiscoveredResourceDetails> invokeDiscoveryComponent(ResourceContainer parentResourceContainer, ResourceDiscoveryComponent component, ResourceDiscoveryContext context) throws Exception {
+ Resource parentResource = parentResourceContainer == null ? null : parentResourceContainer.getResource(); + + if (resourceUpgradeDelegate.hasUpgradeFailedInChildren(parentResource, context.getResourceType())) { + log.debug("Discovery of [" + context.getResourceType() + "] has been disallowed under " + (parentResource == null ? " the platform " : parentResource) + + " because some of its siblings failed to upgrade."); + return null; + } + long timeout = getDiscoveryComponentTimeout(context.getResourceType());
try { @@ -687,7 +695,7 @@ public class InventoryManager extends AgentService implements ContainerService,
// Ask the plugin's discovery component to find the new resource, throwing exceptions if it cannot be // found at all. - Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(discoveryComponent, + Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentResourceContainer, discoveryComponent, discoveryContext); if ((discoveredResources == null) || discoveredResources.isEmpty()) { log.info("Plugin Error: During manual add, discovery component method [" @@ -1207,7 +1215,7 @@ public class InventoryManager extends AgentService implements ContainerService, return resourceContainer.updateAvailability(availabilityType); }
- public void mergeResourceFromUpgrade(Set<ResourceUpgradeRequest> upgradeRequests) { + public void mergeResourcesFromUpgrade(Set<ResourceUpgradeRequest> upgradeRequests) { Set<ResourceUpgradeResponse> serverUpdates = null; try { ServerServices serverServices = this.configuration.getServerServices(); @@ -1430,6 +1438,13 @@ public class InventoryManager extends AgentService implements ContainerService, @SuppressWarnings("unchecked") public void activateResource(Resource resource, @NotNull ResourceContainer container, boolean updatedPluginConfig) throws InvalidPluginConfigurationException, PluginContainerException { + if (resourceUpgradeDelegate.hasUpgradeFailed(resource)) { + if (log.isTraceEnabled()) { + log.trace("Skipping activation of " + resource + " - it has failed to upgrade."); + } + return; + } + ResourceComponent component = container.getResourceComponent();
// if the component already exists and is started, and the resource's plugin config has not changed, there is @@ -1762,7 +1777,7 @@ public class InventoryManager extends AgentService implements ContainerService, * Shutdown the ResourceComponents from the bottom up. * @param resource The resource to deactivate */ - private void deactivateResource(Resource resource) { + public void deactivateResource(Resource resource) { this.inventoryLock.writeLock().lock(); try { ResourceContainer container = getResourceContainer(resource); @@ -1841,7 +1856,7 @@ public class InventoryManager extends AgentService implements ContainerService, Set<DiscoveredResourceDetails> discoveredResources = null;
try { - discoveredResources = invokeDiscoveryComponent(component, context); + discoveredResources = invokeDiscoveryComponent(null, component, context); } catch (Throwable e) { log.warn("Platform plugin discovery failed - skipping", e); } @@ -2043,6 +2058,13 @@ public class InventoryManager extends AgentService implements ContainerService, } }
+ /** + * @return true if the inventory manager failed to merge the upgrade requests with the server during startup. + */ + public boolean hasUpgradeMergeFailed() { + return resourceUpgradeDelegate.hasUpgradeMergeFailed(); + } + /** * Always use this before accessing the event listeners because this ensures * thread safety. @@ -2171,7 +2193,7 @@ public class InventoryManager extends AgentService implements ContainerService, parentResourceContext, SystemInfoFactory.createSystemInfo(), processScanResults, Collections.EMPTY_LIST, this.configuration.getContainerName(), this.configuration .getPluginContainerDeployment()); - Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(discoveryComponent, context); + Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(parentContainer, discoveryComponent, context); newResources = new HashSet<Resource>(); if ((discoveredResources != null) && (!discoveredResources.isEmpty())) { IdentityHashMap<Configuration, DiscoveredResourceDetails> pluginConfigObjects = new IdentityHashMap<Configuration, DiscoveredResourceDetails>(); @@ -2613,6 +2635,12 @@ public class InventoryManager extends AgentService implements ContainerService,
private void upgradeResources() { try { + + if (!configuration.isInsideAgent()) { + log.debug("Skipping resource upgrade in embedded mode."); + return; + } + log.debug("Executing resource upgrade.");
boolean syncResult = handleReport(new InventoryReport(getAgent()), true); @@ -2622,7 +2650,7 @@ public class InventoryManager extends AgentService implements ContainerService, }
upgradeResource(getPlatform()); - + log.debug("Sending the upgrade requests to the server."); resourceUpgradeDelegate.sendRequests();
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java index 025ba3a..98a897e 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java @@ -19,15 +19,17 @@
package org.rhq.core.pc.upgrade;
+import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.rhq.core.clientapi.agent.PluginContainerException; import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.pc.PluginContainer; import org.rhq.core.pc.inventory.InventoryManager; @@ -56,7 +58,10 @@ public class ResourceUpgradeDelegate {
private Set<ResourceUpgradeRequest> requests = new HashSet<ResourceUpgradeRequest>(); private InventoryManager inventoryManager; - + private Set<Resource> failedResources = new HashSet<Resource>(); + private Map<Resource, Set<ResourceType>> failedResourceTypesPerParent = new HashMap<Resource, Set<ResourceType>>(); + private boolean mergeFailed; + public ResourceUpgradeDelegate(InventoryManager inventoryManager) { this.inventoryManager = inventoryManager; } @@ -88,11 +93,56 @@ public class ResourceUpgradeDelegate { } }
- public void sendRequests() { - if (enabled) { - if (requests.size() > 0) { - inventoryManager.mergeResourceFromUpgrade(requests); - requests.clear(); + /** + * @return true if {@link #sendRequests()} threw an exception, false otherwise + */ + public boolean hasUpgradeMergeFailed() { + return mergeFailed; + } + + /** + * Tells whether given resource had a upgrade failure during the {@link #processAndQueue(ResourceContainer)} invocation. + * + * @param resource the resource to test + * @return true if there was an error upgrading this resource, false otherwise + */ + public boolean hasUpgradeFailed(Resource resource) { + return mergeFailed || failedResources.contains(resource); + } + + /** + * Tells whether at least one of the children with given resource type of the given parent resource + * had an upgrade failure during {@link #processAndQueue(ResourceContainer)} invocation. + * + * @return true if at least one of the children of given type failed to upgrade, false otherwise + */ + public boolean hasUpgradeFailedInChildren(Resource parentResource, ResourceType childrenResourceType) { + if (mergeFailed) { + return true; + } + + Set<ResourceType> failedTypes = failedResourceTypesPerParent.get(parentResource); + + return failedTypes != null && failedTypes.contains(childrenResourceType); + } + + public void sendRequests() throws Throwable { + if (enabled && requests.size() > 0) { + try { + inventoryManager.mergeResourcesFromUpgrade(requests); + } catch (Throwable t) { + mergeFailed = true; + + //deactivate all the resources to be upgraded. We might have a problem + //because they have not been upgraded because the merge failed. + for(ResourceUpgradeRequest request : requests) { + ResourceContainer container = inventoryManager.getResourceContainer(request.getResourceId()); + if (container != null) { + inventoryManager.deactivateResource(container.getResource()); + } + } + + throw t; } } } @@ -157,6 +207,20 @@ public class ResourceUpgradeDelegate { if (request.hasSomethingToUpgrade()) { requests.add(request); } + + if (request.getUpgradeErrorMessage() != null) { + failedResources.add(resource); + + Set<ResourceType> failedResourceTypesInParent = failedResourceTypesPerParent.get(parentResource); + if (failedResourceTypesInParent == null) { + failedResourceTypesInParent = new HashSet<ResourceType>(); + failedResourceTypesPerParent.put(parentResource, failedResourceTypesInParent); + } + + failedResourceTypesInParent.add(resource.getResourceType()); + + inventoryManager.deactivateResource(resource); + } }
private String checkUpgradeValid(Resource resource, ResourceUpgradeReport upgradeReport) { diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index 244d2f2..1479345 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -237,6 +237,14 @@ public class ResourceUpgradeTest { TestPayload test = new TestPayload() { public void test(Resource resourceUpgradeTestResource) { assertTrue(resourceUpgradeTestResource.getResourceErrors().size() > 0, "There should be upgrade errors persisted on the server side."); + + //the discovery of the failed resource mustn't have run + ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(resourceUpgradeTestResource); + File dataDir = container.getResourceContext().getDataDirectory(); + + File marker = new File(dataDir, "failing-discovery-ran"); + + assertFalse(marker.exists(), "The discovery of the resource type with a failed upgraded resource must not be executed but it was."); }
@SuppressWarnings("unchecked") diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/DiscComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/DiscComponent.java index 54153e6..75bfbd7 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/DiscComponent.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/DiscComponent.java @@ -19,6 +19,8 @@
package org.rhq.core.pc.upgrade.plugins.failing;
+import java.io.File; +import java.io.IOException; import java.util.Collections; import java.util.Set;
@@ -44,6 +46,20 @@ public class DiscComponent implements ResourceDiscoveryComponent<ResourceCompone
public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent> context) throws InvalidPluginConfigurationException, Exception { + + //create a marker file so that the testing code knows this method has run + File dataDir = context.getParentResourceContext().getDataDirectory(); + if (dataDir != null) { + if (!(dataDir.exists())) { + dataDir.mkdir(); + } + File marker = new File(dataDir, "failing-discovery-ran"); + try { + marker.createNewFile(); + } catch (IOException e) { + } + } + return Collections.singleton(new DiscoveredResourceDetails(context.getResourceType(), RESOURCE_KEY, RESOURCE_NAME, null, RESOURCE_DESCRIPTION, context.getDefaultPluginConfiguration(), null)); } diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java index d1894cb..43c2ba5 100644 --- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java +++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java @@ -91,6 +91,7 @@ import org.rhq.core.domain.cloud.composite.FailoverListComposite.ServerEntry; import org.rhq.core.pc.PluginContainer; import org.rhq.core.pc.PluginContainerConfiguration; import org.rhq.core.pc.ServerServices; +import org.rhq.core.pc.inventory.InventoryManager; import org.rhq.core.pc.plugin.FileSystemPluginFinder; import org.rhq.core.system.SystemInfoFactory; import org.rhq.core.util.ObjectNameFactory; @@ -1591,6 +1592,7 @@ public class AgentMain { * <ul> * <li>Registering with the server (if the agent needs to do so at startup)</li> * <li>Updating the plugins with the latest versions that are found on the server</li> + * <li>Setup a conditional restart of the plugin container, see {@link PluginContainerConditionalRestartListener}</li> * </ul> * * @return <code>true</code> if the agent is not registered or the agent was asked to re-register with the server; @@ -1623,6 +1625,10 @@ public class AgentMain { updatePlugins(); }
+ //the next thing is to setup the conditional restart of the PC if it fails to merge + //the upgrade results with the server due to some network glitch + m_clientSender.addStateListener(new PluginContainerConditionalRestartListener(), false); + return register; }
@@ -3390,6 +3396,42 @@ public class AgentMain { }
/** + * This listener restarts the plugin container upon establishing the connection with the server + * if the following conditions are met: + * <ol> + * <li> The plugin container is started + * <li> It performed the resource upgrade but failed to merge the changes to the server + * </ol> + * By restarting the plugin container in such conditions, we essentially re-run the resource upgrade + * and let the plugin container try to re-merge with the server that we know has just connected. + * + * @author Lukas Krejci + */ + private class PluginContainerConditionalRestartListener implements ClientCommandSenderStateListener { + public boolean startedSending(ClientCommandSender sender) { + try { + InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager(); + if (inventoryManager != null && inventoryManager.hasUpgradeMergeFailed()) { + m_output.println(MSG.getMsg(AgentI18NResourceKeys.RESTARTING_PLUGIN_CONTAINER_AFTER_UPGRADE_MERGE_FAILURE)); + LOG.info(AgentI18NResourceKeys.RESTARTING_PLUGIN_CONTAINER_AFTER_UPGRADE_MERGE_FAILURE); + + PluginContainerPromptCommand pcCommand = new PluginContainerPromptCommand(); + pcCommand.execute(AgentMain.this, new String[] { "stop" }); + pcCommand.execute(AgentMain.this, new String[] { "start" }); + } + } catch (Exception e) { + LOG.error("Failed to restart the plugin container when server connection established."); + } + return true; + } + + public boolean stoppedSending(ClientCommandSender sender) { + //do nothing but keep listening + return true; + } + } + + /** * When the agent starts up, it needs to create the communications servers before starting the plugin container; * however, the agent must not process any incoming commands until after the plugin container fully starts. This * command listener will actually block indefinitely all commands from being processed until its told to open the diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java index eb1df86..c28349c 100644 --- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java +++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java @@ -2050,4 +2050,7 @@ public interface AgentI18NResourceKeys {
@I18NMessage("Done.") String AVAILABILITY_REPORT_SENT = "PromptCommand.availability.sent"; + + @I18NMessage("Restarting the plugin container due to previous failure to merge the upgrade results with the server.") + String RESTARTING_PLUGIN_CONTAINER_AFTER_UPGRADE_MERGE_FAILURE = "AgentMain.pc-conditional-restart"; } \ No newline at end of file diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/DiscoveryPromptCommand.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/DiscoveryPromptCommand.java index 8736f05..1de2dfb 100644 --- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/DiscoveryPromptCommand.java +++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/promptcmd/DiscoveryPromptCommand.java @@ -359,7 +359,7 @@ public class DiscoveryPromptCommand implements AgentPromptCommand { PluginContainerDeployment.AGENT);
Set<DiscoveredResourceDetails> discoveredResources; - discoveredResources = inventoryManager.invokeDiscoveryComponent(discoveryComponent, context); + discoveredResources = inventoryManager.invokeDiscoveryComponent(platformContainer, discoveryComponent, context); if (discoveredResources != null) { for (DiscoveredResourceDetails discoveredResource : discoveredResources) { out.println(MSG.getMsg(AgentI18NResourceKeys.DISCOVERY_COMPONENT_RESULT, discoveredResource diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/PluginContainerConditionalRestart.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/PluginContainerConditionalRestart.java new file mode 100644 index 0000000..b88d097 --- /dev/null +++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/PluginContainerConditionalRestart.java @@ -0,0 +1,31 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.agent; + +import org.testng.annotations.Test; + +/** + * + * @author Lukas Krejci + */ +@Test +public class PluginContainerConditionalRestart { + //TODO implement +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java index 29815cc..95bec5f 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java @@ -23,7 +23,11 @@ import org.rhq.core.domain.resource.composite.ResourceComposite; import org.rhq.enterprise.gui.coregui.client.components.table.Table; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
+import com.smartgwt.client.data.DSCallback; +import com.smartgwt.client.data.DSRequest; +import com.smartgwt.client.data.DSResponse; import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.types.GroupStartOpen; import com.smartgwt.client.widgets.HTMLPane; import com.smartgwt.client.widgets.IButton; import com.smartgwt.client.widgets.Window; @@ -41,43 +45,37 @@ import com.smartgwt.client.widgets.grid.events.CellClickHandler; public class OverviewView extends LocatableVLayout {
private ResourceComposite resourceComposite; - + private OverviewForm form; + private Table errorsGrid; + public OverviewView(String locatorId, ResourceComposite resourceComposite) { super(locatorId); this.resourceComposite = resourceComposite; - } - - @Override - protected void onDraw() { - super.onDraw(); - - setLeft("10%"); - setWidth("80%"); - - if (this.resourceComposite != null) { - onResourceSelected(this.resourceComposite); - } - } - - public void onResourceSelected(ResourceComposite resourceComposite) { - addMember(new OverviewForm(extendLocatorId("form"), resourceComposite)); - buildErrorListGrid(resourceComposite); - } + form = new OverviewForm(extendLocatorId("form"), resourceComposite); + errorsGrid = new Table(extendLocatorId("errors"), "Detected errors", null, null, new String[] { ResourceErrorsDataSource.DETAIL_ID });
- private void buildErrorListGrid(ResourceComposite resourceComposite) { - final Resource resource = resourceComposite.getResource(); - final Table errorsGrid = new Table(extendLocatorId("errors")); + Resource resource = resourceComposite.getResource(); + ResourceErrorsDataSource errors = new ResourceErrorsDataSource(resource.getId());
errorsGrid.setShowFooter(false); -// errorsGrid.getListGrid().setGroupByField(ResourceErrorsDataSource.ERROR_TYPE_ID); -// errorsGrid.getListGrid().setGroupStartOpen(GroupStartOpen.ALL); -// errorsGrid.getListGrid().setShowGroupSummary(true); - - errorsGrid.setDataSource(new ResourceErrorsDataSource(resource.getId())); + errorsGrid.setDataSource(errors);
- //hide only works after we set the datasource - errorsGrid.getListGrid().hideField(ResourceErrorsDataSource.DETAIL_ID); + form.setHeight("*"); + errorsGrid.setHeight("10%");
+ addMember(form); + addMember(errorsGrid); + + } + + @Override + public void onInit() { + super.onInit(); + initErrorsGrid(); + } + + private void initErrorsGrid() { + errorsGrid.setTooltip("Click on the rows to see the error details."); errorsGrid.getListGrid().addCellClickHandler(new CellClickHandler() { public void onCellClick(CellClickEvent event) { ListGridRecord record = event.getRecord(); @@ -113,7 +111,5 @@ public class OverviewView extends LocatableVLayout { w.show(); } }); - - addMember(errorsGrid); } }
commit 34483f9ca83545ab317caf12545531ab5d9b31e9 Merge: b9e1f2c... 24ba997... Author: Lukas Krejci lkrejci@redhat.com Date: Mon Sep 20 16:58:46 2010 +0200
Merge branch 'master' into resource-upgrade
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewForm.java index 074b3c9,0000000..2479c87 mode 100644,000000..100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewForm.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewForm.java @@@ -1,298 -1,0 +1,299 @@@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.summary; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.List; + +import org.rhq.core.domain.measurement.DataType; +import org.rhq.core.domain.measurement.DisplayType; +import org.rhq.core.domain.measurement.MeasurementDataTrait; +import org.rhq.core.domain.measurement.MeasurementDefinition; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.domain.resource.composite.ResourceComposite; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedDynamicForm; +import org.rhq.enterprise.gui.coregui.client.components.form.TogglableTextItem; +import org.rhq.enterprise.gui.coregui.client.components.form.ValueUpdatedHandler; +import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; +import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync; +import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository; +import org.rhq.enterprise.gui.coregui.client.util.message.Message; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.util.SC; +import com.smartgwt.client.widgets.form.fields.FormItem; +import com.smartgwt.client.widgets.form.fields.HeaderItem; +import com.smartgwt.client.widgets.form.fields.SpacerItem; +import com.smartgwt.client.widgets.form.fields.StaticTextItem; + +/** + * The Resource Summary>Overview tab, the form with resource data. + * + * @author Greg Hinkle + * @author Ian Springer + */ +public class OverviewForm extends EnhancedDynamicForm { + + private ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService(); + private ResourceComposite resourceComposite; + - public OverviewForm(ResourceComposite resourceComposite) { ++ public OverviewForm(String locatorId, ResourceComposite resourceComposite) { ++ super(locatorId); + this.resourceComposite = resourceComposite; + } + + @Override + protected void onDraw() { + super.onDraw(); + + setLeft("10%"); + setWidth("80%"); + + if (this.resourceComposite != null) { + setResource(this.resourceComposite); + } + } + + public void setResource(ResourceComposite resourceComposite) { + + this.resourceComposite = resourceComposite; + Resource resource = resourceComposite.getResource(); + + // Load metric defs. + ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(), + EnumSet.of(ResourceTypeRepository.MetadataType.measurements), + new ResourceTypeRepository.TypeLoadedCallback() { + public void onTypesLoaded(ResourceType type) { + try { + buildForm(type); + loadTraitValues(); + } catch (Exception e) { + SC.say("Form load failure"); + e.printStackTrace(); + } + } + }); + } + + private void loadTraitValues() { + final Resource resource = resourceComposite.getResource(); + GWTServiceLookup.getMeasurementDataService().findCurrentTraitsForResource( + resource.getId(), + DisplayType.SUMMARY, + new AsyncCallback<List<MeasurementDataTrait>>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("Failed to load traits for " + resource + ".", + caught); + } + + public void onSuccess(List<MeasurementDataTrait> result) { + // TODO: Implement this method. + for (MeasurementDataTrait trait : result) { + String formId = trait.getName().replaceAll("\.", "_").replaceAll(" ", "__"); + FormItem item = getItem(formId); + + if (item != null) { + setValue(formId, trait.getValue()); + } + } + markForRedraw(); + } + } + ); + + } + + private void buildForm(ResourceType type) { + List<MeasurementDefinition> traits = new ArrayList<MeasurementDefinition>(); + + for (MeasurementDefinition measurement : type.getMetricDefinitions()) { + if (measurement.getDataType() == DataType.TRAIT && measurement.getDisplayType() == DisplayType.SUMMARY) { + traits.add(measurement); + } + } + + Collections.sort(traits, new Comparator<MeasurementDefinition>() { + public int compare(MeasurementDefinition o1, MeasurementDefinition o2) { + return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder()); + } + }); + + List<FormItem> formItems = new ArrayList<FormItem>(); + + HeaderItem headerItem = new HeaderItem("header", "Summary"); + headerItem.setValue("Summary"); + formItems.add(headerItem); + + StaticTextItem typeItem = new StaticTextItem("type", "Type"); + typeItem.setTooltip("Plugin: " + type.getPlugin() + "\n<br>" + "Type: " + type.getName()); + typeItem.setValue(type.getName() + " (" + type.getPlugin() + ")"); + formItems.add(typeItem); + + final Resource resource = this.resourceComposite.getResource(); + boolean modifiable = this.resourceComposite.getResourcePermission().isInventory(); + + final FormItem nameItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); + nameItem.setName("name"); + nameItem.setTitle("Name"); + nameItem.setValue(resource.getName()); + if (nameItem instanceof TogglableTextItem) { + TogglableTextItem togglableNameItem = (TogglableTextItem) nameItem; + togglableNameItem.addValueUpdatedHandler(new ValueUpdatedHandler() { + public void onValueUpdated(final String newName) { + final String oldName = resource.getName(); + if (newName.equals(oldName)) { + return; + } + resource.setName(newName); + OverviewForm.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("Failed to change name of Resource with id " + + resource.getId() + + " from "" + oldName + "" to "" + newName + "".", caught); + // We failed to update it on the Server, so change back the Resource and the form item to + // the original value. + resource.setName(oldName); + nameItem.setValue(oldName); + } + + public void onSuccess(Void result) { + CoreGUI.getMessageCenter().notify(new Message("Name of Resource with id " + + resource.getId() + " was changed from "" + + oldName + "" to "" + newName + "".", Message.Severity.Info)); + } + }); + } + }); + } + formItems.add(nameItem); + + final FormItem descriptionItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); + descriptionItem.setName("description"); + descriptionItem.setTitle("Description"); + descriptionItem.setValue(resource.getDescription()); + if (descriptionItem instanceof TogglableTextItem) { + TogglableTextItem togglableDescriptionItem = (TogglableTextItem) descriptionItem; + togglableDescriptionItem.addValueUpdatedHandler(new ValueUpdatedHandler() { + public void onValueUpdated(final String newDescription) { + final String oldDescription = resource.getDescription(); + if (newDescription.equals(oldDescription)) { + return; + } + resource.setDescription(newDescription); + OverviewForm.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("Failed to change description of Resource with id " + + resource.getId() + + " from "" + oldDescription + "" to "" + newDescription + "".", caught); + // We failed to update it on the Server, so change back the Resource and the form item to + // the original value. + resource.setDescription(oldDescription); + descriptionItem.setValue(oldDescription); + } + + public void onSuccess(Void result) { + CoreGUI.getMessageCenter().notify(new Message("Description of Resource with id " + + resource.getId() + " was changed from "" + + oldDescription + "" to "" + newDescription + "".", Message.Severity.Info)); + } + }); + } + }); + } + formItems.add(descriptionItem); + + final FormItem locationItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); + locationItem.setName("location"); + locationItem.setTitle("Location"); + locationItem.setValue(resource.getLocation()); + if (locationItem instanceof TogglableTextItem) { + TogglableTextItem togglableNameItem = (TogglableTextItem) locationItem; + togglableNameItem.addValueUpdatedHandler(new ValueUpdatedHandler() { + public void onValueUpdated(final String newLocation) { + final String oldLocation = resource.getLocation(); + if (newLocation.equals(oldLocation)) { + return; + } + resource.setLocation(newLocation); + OverviewForm.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("Failed to change location of Resource with id " + + resource.getId() + + " from "" + oldLocation + "" to "" + newLocation + "".", caught); + // We failed to update it on the Server, so change back the Resource and the form item to + // the original value. + resource.setLocation(oldLocation); + locationItem.setValue(oldLocation); + } + + public void onSuccess(Void result) { + CoreGUI.getMessageCenter().notify(new Message("Location of Resource with id " + + resource.getId() + " was changed from "" + + oldLocation + "" to "" + newLocation + "".", Message.Severity.Info)); + } + }); + } + }); + } + formItems.add(locationItem); + + + StaticTextItem versionItem = new StaticTextItem("version", "Version"); + formItems.add(versionItem); + + StaticTextItem parentItem = new StaticTextItem("parent", "Parent"); + formItems.add(parentItem); + + for (MeasurementDefinition trait : traits) { + String id = trait.getDisplayName().replaceAll("\.", "_").replaceAll(" ", "__"); + + StaticTextItem item = new StaticTextItem(id, trait.getDisplayName()); + item.setTooltip(trait.getDescription()); + formItems.add(item); +// item.setValue("?"); + } + +// SectionItem section = new SectionItem("Summary", "Summary"); +// section.setTitle("Summary"); +// section.setDefaultValue("Summary"); +// section.setCanCollapse(true); +// section.setCellStyle("HidablePlainSectionHeader"); +// section.setItemIds(itemIds.toArray(new String[itemIds.size()])); +// formItems.add(0, section); + + formItems.add(new SpacerItem()); + setItems(formItems.toArray(new FormItem[formItems.size()])); + + setValue("type", type.getName() + " (" + type.getPlugin() + ")"); + setValue("name", resource.getName()); + setValue("description", resource.getDescription()); + setValue("location", resource.getLocation()); + setValue("version", (resource.getVersion() != null) ? resource.getVersion() : "<i>none</i>"); + Resource parentResource = resource.getParentResource(); + setValue("parent", parentResource != null ? + ("<a href="#Resource/" + parentResource.getId() + "">" + + parentResource.getName() + "</a>") : "<i>none</i>"); + } +} diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java index 10bde5b,4cf2119..29815cc --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java @@@ -18,31 -18,49 +18,32 @@@ */ package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.summary;
-import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumSet; -import java.util.List; - -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.smartgwt.client.util.SC; -import com.smartgwt.client.widgets.form.fields.FormItem; -import com.smartgwt.client.widgets.form.fields.HeaderItem; -import com.smartgwt.client.widgets.form.fields.SpacerItem; -import com.smartgwt.client.widgets.form.fields.StaticTextItem; - -import org.rhq.core.domain.measurement.DataType; -import org.rhq.core.domain.measurement.DisplayType; -import org.rhq.core.domain.measurement.MeasurementDataTrait; -import org.rhq.core.domain.measurement.MeasurementDefinition; import org.rhq.core.domain.resource.Resource; -import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.composite.ResourceComposite; -import org.rhq.enterprise.gui.coregui.client.CoreGUI; -import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedDynamicForm; -import org.rhq.enterprise.gui.coregui.client.components.form.TogglableTextItem; -import org.rhq.enterprise.gui.coregui.client.components.form.ValueUpdatedHandler; -import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; -import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync; -import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceSelectListener; -import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository; -import org.rhq.enterprise.gui.coregui.client.util.message.Message; +import org.rhq.enterprise.gui.coregui.client.components.table.Table; ++import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout; + +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.widgets.HTMLPane; +import com.smartgwt.client.widgets.IButton; +import com.smartgwt.client.widgets.Window; +import com.smartgwt.client.widgets.events.ClickEvent; +import com.smartgwt.client.widgets.events.ClickHandler; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.grid.events.CellClickEvent; +import com.smartgwt.client.widgets.grid.events.CellClickHandler; - import com.smartgwt.client.widgets.layout.VLayout;
/** * The Resource Summary>Overview tab. * - * @author Greg Hinkle - * @author Ian Springer + * @author Lukas Krejci */ - public class OverviewView extends VLayout { -public class OverviewView extends EnhancedDynamicForm implements ResourceSelectListener { ++public class OverviewView extends LocatableVLayout {
- private ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService(); private ResourceComposite resourceComposite;
- public OverviewView(ResourceComposite resourceComposite) { + public OverviewView(String locatorId, ResourceComposite resourceComposite) { + super(locatorId); this.resourceComposite = resourceComposite; }
@@@ -59,60 -77,218 +60,60 @@@ }
public void onResourceSelected(ResourceComposite resourceComposite) { - addMember(new OverviewForm(resourceComposite)); - - this.resourceComposite = resourceComposite; - Resource resource = resourceComposite.getResource(); - - // Load metric defs. - ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(), - EnumSet.of(ResourceTypeRepository.MetadataType.measurements), - new ResourceTypeRepository.TypeLoadedCallback() { - public void onTypesLoaded(ResourceType type) { - try { - buildForm(type); - loadTraitValues(); - } catch (Exception e) { - SC.say("Form load failure"); - e.printStackTrace(); - } - } - }); ++ addMember(new OverviewForm(extendLocatorId("form"), resourceComposite)); + buildErrorListGrid(resourceComposite); }
- private void loadTraitValues() { + private void buildErrorListGrid(ResourceComposite resourceComposite) { final Resource resource = resourceComposite.getResource(); - Table errorsGrid = new Table("Errors"); - GWTServiceLookup.getMeasurementDataService().findCurrentTraitsForResource(resource.getId(), - DisplayType.SUMMARY, new AsyncCallback<List<MeasurementDataTrait>>() { - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError("Failed to load traits for " + resource + ".", caught); - } - - public void onSuccess(List<MeasurementDataTrait> result) { - // TODO: Implement this method. - for (MeasurementDataTrait trait : result) { - String formId = trait.getName().replaceAll("\.", "_").replaceAll(" ", "__"); - FormItem item = getItem(formId); - - if (item != null) { - setValue(formId, trait.getValue()); - } ++ final Table errorsGrid = new Table(extendLocatorId("errors")); + + errorsGrid.setShowFooter(false); +// errorsGrid.getListGrid().setGroupByField(ResourceErrorsDataSource.ERROR_TYPE_ID); +// errorsGrid.getListGrid().setGroupStartOpen(GroupStartOpen.ALL); +// errorsGrid.getListGrid().setShowGroupSummary(true); + + errorsGrid.setDataSource(new ResourceErrorsDataSource(resource.getId())); + + //hide only works after we set the datasource + errorsGrid.getListGrid().hideField(ResourceErrorsDataSource.DETAIL_ID); + + errorsGrid.getListGrid().addCellClickHandler(new CellClickHandler() { + public void onCellClick(CellClickEvent event) { + ListGridRecord record = event.getRecord(); + final Window w = new Window(); + w.setTitle("Error Details"); + w.setIsModal(true); + w.setShowMinimizeButton(false); + w.setShowModalMask(true); + w.setWidth(640); + w.setHeight(480); + w.centerInPage(); + w.setCanDragResize(true); + - VLayout layout = new VLayout(10); ++ LocatableVLayout layout = new LocatableVLayout(errorsGrid.extendLocatorId("dialogLayout"), 10); + layout.setDefaultLayoutAlign(Alignment.CENTER); + layout.setLayoutMargin(10); + + w.addItem(layout); + + HTMLPane details = new HTMLPane(); + details.setContents("<pre>" + record.getAttribute(ResourceErrorsDataSource.DETAIL_ID) + "</pre>"); + layout.addMember(details); + + IButton ok = new IButton("Ok"); + ok.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent event) { + w.destroy(); } - markForRedraw(); - } - }); - - } - - private void buildForm(ResourceType type) { - List<MeasurementDefinition> traits = new ArrayList<MeasurementDefinition>(); - - for (MeasurementDefinition measurement : type.getMetricDefinitions()) { - if (measurement.getDataType() == DataType.TRAIT && measurement.getDisplayType() == DisplayType.SUMMARY) { - traits.add(measurement); - } - } - - Collections.sort(traits, new Comparator<MeasurementDefinition>() { - public int compare(MeasurementDefinition o1, MeasurementDefinition o2) { - return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder()); + }); + + layout.addMember(ok); + + w.show(); } }); - - List<FormItem> formItems = new ArrayList<FormItem>(); - - HeaderItem headerItem = new HeaderItem("header", "Summary"); - headerItem.setValue("Summary"); - formItems.add(headerItem); - - StaticTextItem typeItem = new StaticTextItem("type", "Type"); - typeItem.setTooltip("Plugin: " + type.getPlugin() + "\n<br>" + "Type: " + type.getName()); - typeItem.setValue(type.getName() + " (" + type.getPlugin() + ")"); - formItems.add(typeItem); - - final Resource resource = this.resourceComposite.getResource(); - boolean modifiable = this.resourceComposite.getResourcePermission().isInventory(); - - final FormItem nameItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); - nameItem.setName("name"); - nameItem.setTitle("Name"); - nameItem.setValue(resource.getName()); - if (nameItem instanceof TogglableTextItem) { - TogglableTextItem togglableNameItem = (TogglableTextItem) nameItem; - togglableNameItem.addValueUpdatedHandler(new ValueUpdatedHandler() { - public void onValueUpdated(final String newName) { - final String oldName = resource.getName(); - if (newName.equals(oldName)) { - return; - } - resource.setName(newName); - OverviewView.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError( - "Failed to change name of Resource with id " + resource.getId() + " from "" + oldName - + "" to "" + newName + "".", caught); - // We failed to update it on the Server, so change back the Resource and the form item to - // the original value. - resource.setName(oldName); - nameItem.setValue(oldName); - } - - public void onSuccess(Void result) { - CoreGUI.getMessageCenter().notify( - new Message("Name of Resource with id " + resource.getId() + " was changed from "" - + oldName + "" to "" + newName + "".", Message.Severity.Info)); - } - }); - } - }); - } - formItems.add(nameItem); - - final FormItem descriptionItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); - descriptionItem.setName("description"); - descriptionItem.setTitle("Description"); - descriptionItem.setValue(resource.getDescription()); - if (descriptionItem instanceof TogglableTextItem) { - TogglableTextItem togglableDescriptionItem = (TogglableTextItem) descriptionItem; - togglableDescriptionItem.addValueUpdatedHandler(new ValueUpdatedHandler() { - public void onValueUpdated(final String newDescription) { - final String oldDescription = resource.getDescription(); - if (newDescription.equals(oldDescription)) { - return; - } - resource.setDescription(newDescription); - OverviewView.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError( - "Failed to change description of Resource with id " + resource.getId() + " from "" - + oldDescription + "" to "" + newDescription + "".", caught); - // We failed to update it on the Server, so change back the Resource and the form item to - // the original value. - resource.setDescription(oldDescription); - descriptionItem.setValue(oldDescription); - } - - public void onSuccess(Void result) { - CoreGUI.getMessageCenter().notify( - new Message("Description of Resource with id " + resource.getId() - + " was changed from "" + oldDescription + "" to "" + newDescription + "".", - Message.Severity.Info)); - } - }); - } - }); - } - formItems.add(descriptionItem); - - final FormItem locationItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); - locationItem.setName("location"); - locationItem.setTitle("Location"); - locationItem.setValue(resource.getLocation()); - if (locationItem instanceof TogglableTextItem) { - TogglableTextItem togglableNameItem = (TogglableTextItem) locationItem; - togglableNameItem.addValueUpdatedHandler(new ValueUpdatedHandler() { - public void onValueUpdated(final String newLocation) { - final String oldLocation = resource.getLocation(); - if (newLocation.equals(oldLocation)) { - return; - } - resource.setLocation(newLocation); - OverviewView.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError( - "Failed to change location of Resource with id " + resource.getId() + " from "" - + oldLocation + "" to "" + newLocation + "".", caught); - // We failed to update it on the Server, so change back the Resource and the form item to - // the original value. - resource.setLocation(oldLocation); - locationItem.setValue(oldLocation); - } - - public void onSuccess(Void result) { - CoreGUI.getMessageCenter().notify( - new Message("Location of Resource with id " + resource.getId() + " was changed from "" - + oldLocation + "" to "" + newLocation + "".", Message.Severity.Info)); - } - }); - } - }); - } - formItems.add(locationItem); - - StaticTextItem versionItem = new StaticTextItem("version", "Version"); - formItems.add(versionItem); - - StaticTextItem parentItem = new StaticTextItem("parent", "Parent"); - formItems.add(parentItem); - - for (MeasurementDefinition trait : traits) { - String id = trait.getDisplayName().replaceAll("\.", "_").replaceAll(" ", "__"); - - StaticTextItem item = new StaticTextItem(id, trait.getDisplayName()); - item.setTooltip(trait.getDescription()); - formItems.add(item); - // item.setValue("?"); - } - - // SectionItem section = new SectionItem("Summary", "Summary"); - // section.setTitle("Summary"); - // section.setDefaultValue("Summary"); - // section.setCanCollapse(true); - // section.setCellStyle("HidablePlainSectionHeader"); - // section.setItemIds(itemIds.toArray(new String[itemIds.size()])); - // formItems.add(0, section); - - formItems.add(new SpacerItem()); - setItems(formItems.toArray(new FormItem[formItems.size()])); - - setValue("type", type.getName() + " (" + type.getPlugin() + ")"); - setValue("name", resource.getName()); - setValue("description", resource.getDescription()); - setValue("location", resource.getLocation()); - setValue("version", (resource.getVersion() != null) ? resource.getVersion() : "<i>none</i>"); - Resource parentResource = resource.getParentResource(); - setValue("parent", parentResource != null ? ("<a href="#Resource/" + parentResource.getId() + "">" - + parentResource.getName() + "</a>") : "<i>none</i>"); + + addMember(errorsGrid); } } diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java index 267b0f1,dd5e77b..4ac0f61 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java @@@ -225,8 -226,18 +227,22 @@@ public abstract class RPCDataSource<T> addField(field); } } + + public void addFields(DataSourceField... fields) { + addFields(Arrays.asList(fields)); + } + + public ListGridRecord getEditedRecord(DSRequest request) { + // Retrieving values before edit + JavaScriptObject oldValues = request.getAttributeAsJavaScriptObject("oldValues"); + // Creating new record for combining old values with changes + ListGridRecord newRecord = new ListGridRecord(); + // Copying properties from old record + JSOHelper.apply(oldValues, newRecord.getJsObj()); + // Retrieving changed values + JavaScriptObject data = request.getData(); + // Apply changes + JSOHelper.apply(data, newRecord.getJsObj()); + return newRecord; + } }
commit b9e1f2c995a66a147793c72dbeb13df7c162128e Merge: 0cd6acd... e5fac0a... Author: Lukas Krejci lkrejci@redhat.com Date: Tue Sep 14 18:33:01 2010 +0200
Merge branch 'master' into resource-upgrade
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java index c06d0c2,b282e41..5990b60 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java @@@ -28,7 -28,8 +28,9 @@@ import org.rhq.core.domain.configuratio import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceError; + import org.rhq.core.domain.resource.composite.DisambiguationReport; + import org.rhq.core.domain.resource.composite.ProblemResourceComposite; import org.rhq.core.domain.resource.composite.RecentlyAddedResourceComposite; import org.rhq.core.domain.resource.composite.ResourceComposite; import org.rhq.core.domain.util.PageControl; @@@ -65,7 -68,5 +69,7 @@@ public interface ResourceGWTService ext void ignoreResources(Integer[] resourceIds);
void unignoreResources(Integer[] resourceIds); + + List<ResourceError> findResourceErrors(int resourceId);
--} ++} diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java index e63978a,ac2abc2..10bde5b --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java @@@ -18,33 -18,50 +18,31 @@@ */ package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.summary;
-import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumSet; -import java.util.List; - -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.smartgwt.client.util.SC; -import com.smartgwt.client.widgets.form.fields.FormItem; -import com.smartgwt.client.widgets.form.fields.HeaderItem; -import com.smartgwt.client.widgets.form.fields.SpacerItem; -import com.smartgwt.client.widgets.form.fields.StaticTextItem; - -import org.rhq.core.domain.measurement.DataType; -import org.rhq.core.domain.measurement.DisplayType; -import org.rhq.core.domain.measurement.MeasurementDataTrait; -import org.rhq.core.domain.measurement.MeasurementDefinition; import org.rhq.core.domain.resource.Resource; -import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.composite.ResourceComposite; -import org.rhq.enterprise.gui.coregui.client.CoreGUI; -import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedDynamicForm; -import org.rhq.enterprise.gui.coregui.client.components.form.TogglableTextItem; -import org.rhq.enterprise.gui.coregui.client.components.form.ValueUpdatedHandler; -import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; -import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync; -import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceSelectListener; -import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository; -import org.rhq.enterprise.gui.coregui.client.util.message.Message; +import org.rhq.enterprise.gui.coregui.client.components.table.Table; - import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceSelectListener; + +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.widgets.HTMLPane; +import com.smartgwt.client.widgets.IButton; +import com.smartgwt.client.widgets.Window; +import com.smartgwt.client.widgets.events.ClickEvent; +import com.smartgwt.client.widgets.events.ClickHandler; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.grid.events.CellClickEvent; +import com.smartgwt.client.widgets.grid.events.CellClickHandler; +import com.smartgwt.client.widgets.layout.VLayout;
/** * The Resource Summary>Overview tab. * - * @author Greg Hinkle - * @author Ian Springer + * @author Lukas Krejci */ - public class OverviewView extends VLayout implements ResourceSelectListener { -public class OverviewView extends EnhancedDynamicForm implements ResourceSelectListener { ++public class OverviewView extends VLayout {
- private ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService(); private ResourceComposite resourceComposite;
- public OverviewView(ResourceComposite resourceComposite) { -- super(); this.resourceComposite = resourceComposite; }
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java index 4f3f3ce,cb2768f..267b0f1 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java @@@ -18,9 -18,10 +18,11 @@@ */ package org.rhq.enterprise.gui.coregui.client.util;
+import java.util.Arrays; + import java.util.ArrayList; import java.util.Collection; import java.util.List; + import java.util.Map;
import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.data.DSResponse; @@@ -183,11 -221,7 +222,11 @@@ public abstract class RPCDataSource<T> */ public void addFields(List<DataSourceField> fields) { for (DataSourceField field : fields) { - addField(field); + addField(field); } } + + public void addFields(DataSourceField... fields) { + addFields(Arrays.asList(fields)); + } } diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java index b933248,25b19b0..6db01f8 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java @@@ -35,7 -35,8 +35,9 @@@ import org.rhq.core.domain.configuratio import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceError; + import org.rhq.core.domain.resource.composite.DisambiguationReport; + import org.rhq.core.domain.resource.composite.ProblemResourceComposite; import org.rhq.core.domain.resource.composite.RecentlyAddedResourceComposite; import org.rhq.core.domain.resource.composite.ResourceComposite; import org.rhq.core.domain.util.PageControl; @@@ -215,9 -239,5 +240,9 @@@ public class ResourceGWTServiceImpl ext public void unignoreResources(Integer[] resourceIds) { discoveryBoss.unignoreResources(getSessionSubject(), resourceIds); } - -} + + public List<ResourceError> findResourceErrors(int resourceId) { + return SerialUtility.prepare(resourceManager.findResourceErrors(getSessionSubject(), resourceId), + "ResourceService.getResourceErrors"); + } - } ++}
commit 0cd6acd2fe93a35a9b2cdbde0828c416ac49f67d Author: Lukas Krejci lkrejci@redhat.com Date: Tue Aug 24 17:48:01 2010 +0200
Make tests work with the changed test plugin jars location, added tests for upgrade failure reporting.
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java index 19c1d95..adb3989 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java @@ -43,6 +43,8 @@ import org.rhq.core.clientapi.server.discovery.InventoryReport; import org.rhq.core.domain.discovery.ResourceSyncInfo; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceError; +import org.rhq.core.domain.resource.ResourceErrorType; import org.rhq.core.domain.resource.ResourceType;
/** @@ -137,6 +139,11 @@ public class FakeServerInventory { resource.setResourceKey(request.getNewResourceKey()); }
+ if (request.getUpgradeErrorMessage() != null) { + ResourceError error = new ResourceError(resource, ResourceErrorType.UPGRADE, request.getUpgradeErrorMessage(), request.getUpgradeErrorStackTrace(), request.getTimestamp()); + resource.getResourceErrors().add(error); + } + ResourceUpgradeResponse resp = new ResourceUpgradeResponse(); resp.setResourceId(resource.getId()); resp.setUpgradedResourceName(resource.getName()); diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index 202e0c0..244d2f2 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -69,8 +69,9 @@ import org.rhq.core.pc.plugin.FileSystemPluginFinder; @Test(sequential = true, invocationCount = 1) public class ResourceUpgradeTest {
- private static final String PLUGIN_V1_FILENAME = "resource-upgrade-test-plugin-1.0.0.jar"; - private static final String PLUGIN_V2_FILENAME = "resource-upgrade-test-plugin-2.0.0.jar"; + private static final String PLUGIN_V1_FILENAME = "/resource-upgrade-test-plugin-1.0.0.jar"; + private static final String PLUGIN_V2_FILENAME = "/resource-upgrade-test-plugin-2.0.0.jar"; + private static final String FAILING_PLUGIN_FILE_NAME = "/resource-upgrade-test-plugin-3.0.0.jar";
private static final String PLUGINS_DIR_NAME = "plugins"; private static final String DATA_DIR_NAME = "data"; @@ -101,6 +102,7 @@ public class ResourceUpgradeTest { public void sanityCheck() { verifyPluginExists(PLUGIN_V1_FILENAME); verifyPluginExists(PLUGIN_V2_FILENAME); + verifyPluginExists(FAILING_PLUGIN_FILE_NAME); }
@BeforeClass(dependsOnMethods = "sanityCheck") @@ -227,6 +229,35 @@ public class ResourceUpgradeTest { executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, test); }
+ @Test + public void testUpgradeFailureHandling() throws Exception { + currentServerSideInventory = new FakeServerInventory(); + initialSyncAndDiscovery(InventoryStatus.COMMITTED); + + TestPayload test = new TestPayload() { + public void test(Resource resourceUpgradeTestResource) { + assertTrue(resourceUpgradeTestResource.getResourceErrors().size() > 0, "There should be upgrade errors persisted on the server side."); + } + + @SuppressWarnings("unchecked") + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + + between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); + will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + + oneOf(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); + will(currentServerSideInventory.upgradeResources()); + } + }; + } + }; + + executeTestWithPlugins(Collections.singleton(FAILING_PLUGIN_FILE_NAME), false, test); + } + private void initialSyncAndDiscovery(final InventoryStatus requiredInventoryStatus) throws Exception { cleanDataDir(); executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), true, new TestPayload() {
commit 90b602f22c280ee63deb7e51470db1fcda9b79a1 Author: Lukas Krejci lkrejci@redhat.com Date: Tue Aug 24 17:46:58 2010 +0200
Final touches on the Server side error reporting.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java index cc63040..e63978a 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java @@ -24,7 +24,6 @@ import org.rhq.enterprise.gui.coregui.client.components.table.Table; import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceSelectListener;
import com.smartgwt.client.types.Alignment; -import com.smartgwt.client.types.GroupStartOpen; import com.smartgwt.client.widgets.HTMLPane; import com.smartgwt.client.widgets.IButton; import com.smartgwt.client.widgets.Window; @@ -33,7 +32,6 @@ import com.smartgwt.client.widgets.events.ClickHandler; import com.smartgwt.client.widgets.grid.ListGridRecord; import com.smartgwt.client.widgets.grid.events.CellClickEvent; import com.smartgwt.client.widgets.grid.events.CellClickHandler; -import com.smartgwt.client.widgets.layout.HLayout; import com.smartgwt.client.widgets.layout.VLayout;
/** @@ -92,9 +90,10 @@ public class OverviewView extends VLayout implements ResourceSelectListener { w.setWidth(640); w.setHeight(480); w.centerInPage(); + w.setCanDragResize(true);
VLayout layout = new VLayout(10); - layout.setLayoutAlign(Alignment.CENTER); + layout.setDefaultLayoutAlign(Alignment.CENTER); layout.setLayoutMargin(10);
w.addItem(layout); @@ -109,7 +108,6 @@ public class OverviewView extends VLayout implements ResourceSelectListener { w.destroy(); } }); - ok.setAlign(Alignment.CENTER);
layout.addMember(ok);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ResourceErrorsDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ResourceErrorsDataSource.java index 4957fc7..1843f2b 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ResourceErrorsDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ResourceErrorsDataSource.java @@ -90,7 +90,7 @@ public class ResourceErrorsDataSource extends RPCDataSource<ResourceError> { ListGridRecord record = new ListGridRecord();
record.setAttribute(DETAIL_ID, from.getDetail()); - record.setAttribute(ERROR_TYPE_ID, from.getErrorType()); + record.setAttribute(ERROR_TYPE_ID, from.getErrorType().toString()); record.setAttribute(SUMMARY_ID, from.getSummary()); record.setAttribute(TIME_OCCURED_ID, new Date(from.getTimeOccurred()));
commit f0b6cda14af2bce898dd6af66b4bb2627a836d72 Merge: d689f70... 66234db... Author: Lukas Krejci lkrejci@redhat.com Date: Tue Aug 24 13:25:05 2010 +0200
Merge branch 'master' into resource-upgrade
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java index 1ea9630,950d28c..4f3f3ce --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java @@@ -18,8 -18,8 +18,9 @@@ */ package org.rhq.enterprise.gui.coregui.client.util;
+import java.util.Arrays; import java.util.Collection; + import java.util.List;
import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.data.DSResponse; @@@ -172,13 -173,16 +174,20 @@@ public abstract class RPCDataSource<T> return response; }
- public void addFields(Collection<DataSourceField> fields) { + /** + * Add the specified fields to this data source. When the data source is associated with a + * {@link com.smartgwt.client.widgets.grid.ListGrid}, the fields will be displayed in the order they are specified + * here. + * + * @param fields the fields to be added + */ + public void addFields(List<DataSourceField> fields) { for (DataSourceField field : fields) { - addField(field); + addField(field); } } + + public void addFields(DataSourceField... fields) { + addFields(Arrays.asList(fields)); + } }
commit d689f70de060cdb776cea923f759f0e5de226955 Author: Lukas Krejci lkrejci@redhat.com Date: Tue Aug 24 13:17:24 2010 +0200
Upgrade errors (and other resource errors) shown in the summary tab. Not everything seems to work yet.
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java index 9532920..aca9c90 100644 --- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java @@ -41,7 +41,7 @@ public class ResourceUpgradeRequest extends ResourceUpgradeReport { private String upgradeErrorMessage; private String upgradeErrorStackTrace; private long timestamp; - + public ResourceUpgradeRequest(int resourceId) { this.resourceId = resourceId; } @@ -74,14 +74,37 @@ public class ResourceUpgradeRequest extends ResourceUpgradeReport { public long getTimestamp() { return timestamp; } - + public void setTimestamp(long timestamp) { this.timestamp = timestamp; } - + public void setErrorProperties(Throwable t) { - upgradeErrorMessage = t.getMessage(); + upgradeErrorMessage = null; + upgradeErrorStackTrace = null; + + //first try to extract an error message from the exception + //or some of its parents + Throwable p = t; + while (upgradeErrorMessage == null && p != null) { + upgradeErrorMessage = p.getMessage(); + if (upgradeErrorMessage == null) { + upgradeErrorMessage = p.getLocalizedMessage(); + } + p = p.getCause(); + } + + //ok, we have no error messages. But we have to supply something + //as the message, so let's use the class name as a last resort. + if (upgradeErrorMessage == null) { + if (t.getClass().getCanonicalName() != null) { + upgradeErrorMessage = t.getClass().getCanonicalName(); + } else if (t.getClass().getName() != null) { + upgradeErrorMessage = t.getClass().getName(); + } + }
+ //print the stack trace into a string StringWriter string = new StringWriter(); PrintWriter w = new PrintWriter(string); t.printStackTrace(w); diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceErrorTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceErrorTest.java index 8fdc2f7..6630d4b 100644 --- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceErrorTest.java +++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceErrorTest.java @@ -92,7 +92,7 @@ public class ResourceErrorTest extends AbstractEJB3Test { q.setParameter("resourceId", newResource.getId()); assert q.getResultList().size() == 2;
- q = em.createNamedQuery(ResourceError.QUERY_FIND_BY_RESOURCE_ID_AND_ERROR_TYPE); + q = em.createNamedQuery(ResourceError.QUERY_FIND_BY_RESOURCE_ID_AND_ERROR_TYPES); q.setParameter("resourceId", newResource.getId()); q.setParameter("errorType", ResourceErrorType.INVALID_PLUGIN_CONFIGURATION); assert q.getResultList().size() == 2; @@ -129,7 +129,7 @@ public class ResourceErrorTest extends AbstractEJB3Test { assert errors.get(0).getDetail().equals("test detail"); assert errors.get(0).getTimeOccurred() == 12345;
- q = em.createNamedQuery(ResourceError.QUERY_FIND_BY_RESOURCE_ID_AND_ERROR_TYPE); + q = em.createNamedQuery(ResourceError.QUERY_FIND_BY_RESOURCE_ID_AND_ERROR_TYPES); q.setParameter("resourceId", newResource.getId()); q.setParameter("errorType", ResourceErrorType.INVALID_PLUGIN_CONFIGURATION); errors = q.getResultList(); diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml index a4ca249..4b09ef8 100644 --- a/modules/core/plugin-container/pom.xml +++ b/modules/core/plugin-container/pom.xml @@ -163,26 +163,39 @@ <id>process-test-classes</id> <phase>process-test-classes</phase> <configuration> - <tasks> - <echo>Assembling the two resource upgrade test plugins</echo> - <copy toDir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v1/META-INF"> + <tasks unless="maven.test.skip"> + <echo>Assembling the resource upgrade test plugins</echo> + <copy toDir="${project.build.testOutputDirectory}/tmp/v1/META-INF"> <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/v1/rhq-plugin.xml" /> </copy> - <jar destfile="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-1.0.0.jar"> - <fileset dir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v1" includes="*.class,**/rhq-plugin.xml" /> + <copy toDir="${project.build.testOutputDirectory}/tmp/v1/org/rhq/core/pc/upgrade/plugins/v1"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v1/*.class" /> + </copy> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-1.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/v1" includes="**/*.class,**/rhq-plugin.xml" /> </jar> - <copy toDir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v2/META-INF"> + + <copy toDir="${project.build.testOutputDirectory}/tmp/v2/META-INF"> <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/v2/rhq-plugin.xml" /> </copy> - <jar destfile="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar"> - <fileset dir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v2" includes="*.class,**/rhq-plugin.xml" /> + <copy toDir="${project.build.testOutputDirectory}/tmp/v2/org/rhq/core/pc/upgrade/plugins/v2"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v2/*.class" /> + </copy> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-2.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/v2" includes="**/*.class,**/rhq-plugin.xml" /> </jar> - <copy toDir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/failing/META-INF"> + + <copy toDir="${project.build.testOutputDirectory}/tmp/failing/META-INF"> <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/failing/rhq-plugin.xml" /> </copy> - <jar destfile="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-3.0.0.jar"> - <fileset dir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/failing" includes="*.class,**/rhq-plugin.xml" /> + <copy toDir="${project.build.testOutputDirectory}/tmp/failing/org/rhq/core/pc/upgrade/plugins/failing"> + <fileset file="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/failing/*.class" /> + </copy> + <jar destfile="${project.build.testOutputDirectory}/resource-upgrade-test-plugin-3.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/tmp/failing" includes="**/*.class,**/rhq-plugin.xml" /> </jar> + + <delete dir="${project.build.testOutputDirectory}/tmp"/> </tasks> </configuration> <goals> diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java index f92e7d5..c06d0c2 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java @@ -28,6 +28,7 @@ import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.composite.RecentlyAddedResourceComposite; import org.rhq.core.domain.resource.composite.ResourceComposite; import org.rhq.core.domain.util.PageControl; @@ -64,5 +65,7 @@ public interface ResourceGWTService extends RemoteService { void ignoreResources(Integer[] resourceIds);
void unignoreResources(Integer[] resourceIds); + + List<ResourceError> findResourceErrors(int resourceId);
} \ No newline at end of file diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java index 2fff538..cc63040 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java @@ -18,20 +18,22 @@ */ package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.summary;
-import java.util.ArrayList; -import java.util.List; - import org.rhq.core.domain.resource.Resource; -import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.composite.ResourceComposite; +import org.rhq.enterprise.gui.coregui.client.components.table.Table; import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceSelectListener;
-import com.smartgwt.client.util.SC; -import com.smartgwt.client.widgets.grid.ListGrid; -import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.types.GroupStartOpen; +import com.smartgwt.client.widgets.HTMLPane; +import com.smartgwt.client.widgets.IButton; +import com.smartgwt.client.widgets.Window; +import com.smartgwt.client.widgets.events.ClickEvent; +import com.smartgwt.client.widgets.events.ClickHandler; import com.smartgwt.client.widgets.grid.ListGridRecord; -import com.smartgwt.client.widgets.grid.events.RecordClickEvent; -import com.smartgwt.client.widgets.grid.events.RecordClickHandler; +import com.smartgwt.client.widgets.grid.events.CellClickEvent; +import com.smartgwt.client.widgets.grid.events.CellClickHandler; +import com.smartgwt.client.widgets.layout.HLayout; import com.smartgwt.client.widgets.layout.VLayout;
/** @@ -62,41 +64,59 @@ public class OverviewView extends VLayout implements ResourceSelectListener {
public void onResourceSelected(ResourceComposite resourceComposite) { addMember(new OverviewForm(resourceComposite)); - ListGrid errorsGrid = buildErrorListGrid(resourceComposite); - if (errorsGrid != null) { - addMember(errorsGrid); - } + buildErrorListGrid(resourceComposite); }
- private static ListGrid buildErrorListGrid(ResourceComposite resourceComposite) { + private void buildErrorListGrid(ResourceComposite resourceComposite) { final Resource resource = resourceComposite.getResource(); - ListGrid errorsGrid = null; - if (resource.getResourceErrors() != null && resource.getResourceErrors().size() > 0) { - errorsGrid = new ListGrid(); - - ListGridField summaryField = new ListGridField("summary", "Errors"); - summaryField.addRecordClickHandler(new RecordClickHandler() { - - @Override - public void onRecordClick(RecordClickEvent event) { - String detail = event.getRecord().getAttribute("detail"); - SC.say("Error details", detail); - } - }); - - errorsGrid.setFields(summaryField); - - List<ListGridRecord> errorList = new ArrayList<ListGridRecord>(); - for (ResourceError error : resource.getResourceErrors()) { - ListGridRecord record = new ListGridRecord(); - record.setAttribute("summary", error.getSummary()); - record.setAttribute("detail", error.getDetail()); - errorList.add(record); + Table errorsGrid = new Table("Errors"); + + errorsGrid.setShowFooter(false); +// errorsGrid.getListGrid().setGroupByField(ResourceErrorsDataSource.ERROR_TYPE_ID); +// errorsGrid.getListGrid().setGroupStartOpen(GroupStartOpen.ALL); +// errorsGrid.getListGrid().setShowGroupSummary(true); + + errorsGrid.setDataSource(new ResourceErrorsDataSource(resource.getId())); + + //hide only works after we set the datasource + errorsGrid.getListGrid().hideField(ResourceErrorsDataSource.DETAIL_ID); + + errorsGrid.getListGrid().addCellClickHandler(new CellClickHandler() { + public void onCellClick(CellClickEvent event) { + ListGridRecord record = event.getRecord(); + final Window w = new Window(); + w.setTitle("Error Details"); + w.setIsModal(true); + w.setShowMinimizeButton(false); + w.setShowModalMask(true); + w.setWidth(640); + w.setHeight(480); + w.centerInPage(); + + VLayout layout = new VLayout(10); + layout.setLayoutAlign(Alignment.CENTER); + layout.setLayoutMargin(10); + + w.addItem(layout); + + HTMLPane details = new HTMLPane(); + details.setContents("<pre>" + record.getAttribute(ResourceErrorsDataSource.DETAIL_ID) + "</pre>"); + layout.addMember(details); + + IButton ok = new IButton("Ok"); + ok.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent event) { + w.destroy(); + } + }); + ok.setAlign(Alignment.CENTER); + + layout.addMember(ok); + + w.show(); } - - errorsGrid.setRecords(errorList.toArray(new ListGridRecord[errorList.size()])); - } - - return errorsGrid; + }); + + addMember(errorsGrid); } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ResourceErrorsDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ResourceErrorsDataSource.java new file mode 100644 index 0000000..4957fc7 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/ResourceErrorsDataSource.java @@ -0,0 +1,100 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.summary; + +import java.util.Date; +import java.util.List; + +import org.rhq.core.domain.resource.ResourceError; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; +import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync; +import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.data.DSRequest; +import com.smartgwt.client.data.DSResponse; +import com.smartgwt.client.data.fields.DataSourceDateField; +import com.smartgwt.client.data.fields.DataSourceDateTimeField; +import com.smartgwt.client.data.fields.DataSourceEnumField; +import com.smartgwt.client.data.fields.DataSourceTextField; +import com.smartgwt.client.rpc.RPCResponse; +import com.smartgwt.client.widgets.grid.ListGridRecord; + +/** + * + * @author Lukas Krejci + */ +public class ResourceErrorsDataSource extends RPCDataSource<ResourceError> { + + public static final String SUMMARY_ID = "summary"; + public static final String DETAIL_ID = "detail"; + public static final String ERROR_TYPE_ID = "errorType"; + public static final String TIME_OCCURED_ID = "timeOccured"; + + ResourceGWTServiceAsync resourceService; + int resourceId; + + public ResourceErrorsDataSource(int resourceId) { + resourceService = GWTServiceLookup.getResourceService(); + this.resourceId = resourceId; + + addFields(new DataSourceTextField(SUMMARY_ID, "Summary"), + new DataSourceTextField(DETAIL_ID, "Detailed Message"), + new DataSourceEnumField(ERROR_TYPE_ID, "Error Type"), new DataSourceDateTimeField(TIME_OCCURED_ID, "Time")); + } + + /* (non-Javadoc) + * @see org.rhq.enterprise.gui.coregui.client.util.RPCDataSource#executeFetch(com.smartgwt.client.data.DSRequest, com.smartgwt.client.data.DSResponse) + */ + @Override + protected void executeFetch(final DSRequest request, final DSResponse response) { + resourceService.findResourceErrors(resourceId, new AsyncCallback<List<ResourceError>>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError( + "Failed to find resource errors for resource with id: " + resourceId, caught); + response.setStatus(RPCResponse.STATUS_FAILURE); + processResponse(request.getRequestId(), response); + } + + public void onSuccess(List<ResourceError> result) { + response.setData(buildRecords(result)); + processResponse(request.getRequestId(), response); + }; + }); + } + + public ResourceError copyValues(ListGridRecord from) { + //This is read-only datasource, so no need to implement this. + return null; + } + + public ListGridRecord copyValues(ResourceError from) { + ListGridRecord record = new ListGridRecord(); + + record.setAttribute(DETAIL_ID, from.getDetail()); + record.setAttribute(ERROR_TYPE_ID, from.getErrorType()); + record.setAttribute(SUMMARY_ID, from.getSummary()); + record.setAttribute(TIME_OCCURED_ID, new Date(from.getTimeOccurred())); + + return record; + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java index 1b6f6cd..1ea9630 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.gui.coregui.client.util;
+import java.util.Arrays; import java.util.Collection;
import com.smartgwt.client.data.DSRequest; @@ -176,4 +177,8 @@ public abstract class RPCDataSource<T> extends DataSource { addField(field); } } + + public void addFields(DataSourceField... fields) { + addFields(Arrays.asList(fields)); + } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java index c10254e..b933248 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java @@ -35,6 +35,7 @@ import org.rhq.core.domain.configuration.definition.ConfigurationTemplate; import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.composite.RecentlyAddedResourceComposite; import org.rhq.core.domain.resource.composite.ResourceComposite; import org.rhq.core.domain.util.PageControl; @@ -215,4 +216,8 @@ public class ResourceGWTServiceImpl extends AbstractGWTServiceImpl implements Re discoveryBoss.unignoreResources(getSessionSubject(), resourceIds); }
+ public List<ResourceError> findResourceErrors(int resourceId) { + return SerialUtility.prepare(resourceManager.findResourceErrors(getSessionSubject(), resourceId), + "ResourceService.getResourceErrors"); + } } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index b773384..a480fb7 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -486,7 +486,7 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot private ResourceUpgradeResponse upgradeResource(@NotNull Resource resource, ResourceUpgradeRequest upgradeRequest, boolean allowGenericPropertiesUpgrade) { if (upgradeRequest.getUpgradeErrorMessage() != null) { ResourceError error = new ResourceError(resource, ResourceErrorType.UPGRADE, upgradeRequest.getUpgradeErrorMessage(), upgradeRequest.getUpgradeErrorStackTrace(), upgradeRequest.getTimestamp()); - entityManager.persist(error); + resourceManager.addResourceError(error); return null; }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java index 5a4cf92..29672cc 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java @@ -1708,6 +1708,21 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage return query.getResultList(); }
+ @NotNull + @SuppressWarnings("unchecked") + public List<ResourceError> findResourceErrors(Subject user, int resourceId) { + // do authz check + if (!authorizationManager.canViewResource(user, resourceId)) { + throw new PermissionException("User [" + user + "] does not have permission to view resource [" + + resourceId + "]"); + } + + // we passed authz check, now get the errors + Query query = entityManager.createNamedQuery(ResourceError.QUERY_FIND_BY_RESOURCE_ID); + query.setParameter("resourceId", resourceId); + return query.getResultList(); + } + public void addResourceError(ResourceError resourceError) { Subject overlord = subjectManager.getOverlord(); Resource resource; @@ -1718,9 +1733,10 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage }
if (resourceError.getErrorType() == ResourceErrorType.INVALID_PLUGIN_CONFIGURATION - || resourceError.getErrorType() == ResourceErrorType.AVAILABILITY_CHECK) { - // there should be at most one invalid plugin configuration error and one availability check error per - // resource, so delete any currently existing ones before we add this new one + || resourceError.getErrorType() == ResourceErrorType.AVAILABILITY_CHECK + || resourceError.getErrorType() == ResourceErrorType.UPGRADE) { + // there should be at most one invalid plugin configuration error, availability check + // or upgrade error per resource, so delete any currently existing ones before we add this new one List<ResourceError> doomedErrors = resource.getResourceErrors(resourceError.getErrorType());
// there should only ever be at most 1, but loop through the list just in case something got screwed up diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java index a2f26ff..b84a104 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java @@ -319,6 +319,17 @@ public interface ResourceManagerLocal { List<ResourceError> findResourceErrors(Subject user, int resourceId, ResourceErrorType errorType);
/** + * Returns all the errors that have occurred for the given resource. + * + * @param user the user asking to see the errors + * @param resourceId the resource whose errors are to be returned + * + * @return the list of resource errors + */ + @NotNull + List<ResourceError> findResourceErrors(Subject user, int resourceId); + + /** * Indicates an error occurred on a resource. The given error will be associated with the resource found in the * error. *
commit 4e8ae3349ff28b025741a1c3bb0d1a827c0feff8 Author: Lukas Krejci lkrejci@redhat.com Date: Fri Aug 20 15:14:27 2010 +0200
first stab at the errors display GUI.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewForm.java new file mode 100644 index 0000000..074b3c9 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewForm.java @@ -0,0 +1,298 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.summary; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.List; + +import org.rhq.core.domain.measurement.DataType; +import org.rhq.core.domain.measurement.DisplayType; +import org.rhq.core.domain.measurement.MeasurementDataTrait; +import org.rhq.core.domain.measurement.MeasurementDefinition; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.domain.resource.composite.ResourceComposite; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedDynamicForm; +import org.rhq.enterprise.gui.coregui.client.components.form.TogglableTextItem; +import org.rhq.enterprise.gui.coregui.client.components.form.ValueUpdatedHandler; +import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; +import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync; +import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository; +import org.rhq.enterprise.gui.coregui.client.util.message.Message; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.util.SC; +import com.smartgwt.client.widgets.form.fields.FormItem; +import com.smartgwt.client.widgets.form.fields.HeaderItem; +import com.smartgwt.client.widgets.form.fields.SpacerItem; +import com.smartgwt.client.widgets.form.fields.StaticTextItem; + +/** + * The Resource Summary>Overview tab, the form with resource data. + * + * @author Greg Hinkle + * @author Ian Springer + */ +public class OverviewForm extends EnhancedDynamicForm { + + private ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService(); + private ResourceComposite resourceComposite; + + public OverviewForm(ResourceComposite resourceComposite) { + this.resourceComposite = resourceComposite; + } + + @Override + protected void onDraw() { + super.onDraw(); + + setLeft("10%"); + setWidth("80%"); + + if (this.resourceComposite != null) { + setResource(this.resourceComposite); + } + } + + public void setResource(ResourceComposite resourceComposite) { + + this.resourceComposite = resourceComposite; + Resource resource = resourceComposite.getResource(); + + // Load metric defs. + ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(), + EnumSet.of(ResourceTypeRepository.MetadataType.measurements), + new ResourceTypeRepository.TypeLoadedCallback() { + public void onTypesLoaded(ResourceType type) { + try { + buildForm(type); + loadTraitValues(); + } catch (Exception e) { + SC.say("Form load failure"); + e.printStackTrace(); + } + } + }); + } + + private void loadTraitValues() { + final Resource resource = resourceComposite.getResource(); + GWTServiceLookup.getMeasurementDataService().findCurrentTraitsForResource( + resource.getId(), + DisplayType.SUMMARY, + new AsyncCallback<List<MeasurementDataTrait>>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("Failed to load traits for " + resource + ".", + caught); + } + + public void onSuccess(List<MeasurementDataTrait> result) { + // TODO: Implement this method. + for (MeasurementDataTrait trait : result) { + String formId = trait.getName().replaceAll("\.", "_").replaceAll(" ", "__"); + FormItem item = getItem(formId); + + if (item != null) { + setValue(formId, trait.getValue()); + } + } + markForRedraw(); + } + } + ); + + } + + private void buildForm(ResourceType type) { + List<MeasurementDefinition> traits = new ArrayList<MeasurementDefinition>(); + + for (MeasurementDefinition measurement : type.getMetricDefinitions()) { + if (measurement.getDataType() == DataType.TRAIT && measurement.getDisplayType() == DisplayType.SUMMARY) { + traits.add(measurement); + } + } + + Collections.sort(traits, new Comparator<MeasurementDefinition>() { + public int compare(MeasurementDefinition o1, MeasurementDefinition o2) { + return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder()); + } + }); + + List<FormItem> formItems = new ArrayList<FormItem>(); + + HeaderItem headerItem = new HeaderItem("header", "Summary"); + headerItem.setValue("Summary"); + formItems.add(headerItem); + + StaticTextItem typeItem = new StaticTextItem("type", "Type"); + typeItem.setTooltip("Plugin: " + type.getPlugin() + "\n<br>" + "Type: " + type.getName()); + typeItem.setValue(type.getName() + " (" + type.getPlugin() + ")"); + formItems.add(typeItem); + + final Resource resource = this.resourceComposite.getResource(); + boolean modifiable = this.resourceComposite.getResourcePermission().isInventory(); + + final FormItem nameItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); + nameItem.setName("name"); + nameItem.setTitle("Name"); + nameItem.setValue(resource.getName()); + if (nameItem instanceof TogglableTextItem) { + TogglableTextItem togglableNameItem = (TogglableTextItem) nameItem; + togglableNameItem.addValueUpdatedHandler(new ValueUpdatedHandler() { + public void onValueUpdated(final String newName) { + final String oldName = resource.getName(); + if (newName.equals(oldName)) { + return; + } + resource.setName(newName); + OverviewForm.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("Failed to change name of Resource with id " + + resource.getId() + + " from "" + oldName + "" to "" + newName + "".", caught); + // We failed to update it on the Server, so change back the Resource and the form item to + // the original value. + resource.setName(oldName); + nameItem.setValue(oldName); + } + + public void onSuccess(Void result) { + CoreGUI.getMessageCenter().notify(new Message("Name of Resource with id " + + resource.getId() + " was changed from "" + + oldName + "" to "" + newName + "".", Message.Severity.Info)); + } + }); + } + }); + } + formItems.add(nameItem); + + final FormItem descriptionItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); + descriptionItem.setName("description"); + descriptionItem.setTitle("Description"); + descriptionItem.setValue(resource.getDescription()); + if (descriptionItem instanceof TogglableTextItem) { + TogglableTextItem togglableDescriptionItem = (TogglableTextItem) descriptionItem; + togglableDescriptionItem.addValueUpdatedHandler(new ValueUpdatedHandler() { + public void onValueUpdated(final String newDescription) { + final String oldDescription = resource.getDescription(); + if (newDescription.equals(oldDescription)) { + return; + } + resource.setDescription(newDescription); + OverviewForm.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("Failed to change description of Resource with id " + + resource.getId() + + " from "" + oldDescription + "" to "" + newDescription + "".", caught); + // We failed to update it on the Server, so change back the Resource and the form item to + // the original value. + resource.setDescription(oldDescription); + descriptionItem.setValue(oldDescription); + } + + public void onSuccess(Void result) { + CoreGUI.getMessageCenter().notify(new Message("Description of Resource with id " + + resource.getId() + " was changed from "" + + oldDescription + "" to "" + newDescription + "".", Message.Severity.Info)); + } + }); + } + }); + } + formItems.add(descriptionItem); + + final FormItem locationItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); + locationItem.setName("location"); + locationItem.setTitle("Location"); + locationItem.setValue(resource.getLocation()); + if (locationItem instanceof TogglableTextItem) { + TogglableTextItem togglableNameItem = (TogglableTextItem) locationItem; + togglableNameItem.addValueUpdatedHandler(new ValueUpdatedHandler() { + public void onValueUpdated(final String newLocation) { + final String oldLocation = resource.getLocation(); + if (newLocation.equals(oldLocation)) { + return; + } + resource.setLocation(newLocation); + OverviewForm.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("Failed to change location of Resource with id " + + resource.getId() + + " from "" + oldLocation + "" to "" + newLocation + "".", caught); + // We failed to update it on the Server, so change back the Resource and the form item to + // the original value. + resource.setLocation(oldLocation); + locationItem.setValue(oldLocation); + } + + public void onSuccess(Void result) { + CoreGUI.getMessageCenter().notify(new Message("Location of Resource with id " + + resource.getId() + " was changed from "" + + oldLocation + "" to "" + newLocation + "".", Message.Severity.Info)); + } + }); + } + }); + } + formItems.add(locationItem); + + + StaticTextItem versionItem = new StaticTextItem("version", "Version"); + formItems.add(versionItem); + + StaticTextItem parentItem = new StaticTextItem("parent", "Parent"); + formItems.add(parentItem); + + for (MeasurementDefinition trait : traits) { + String id = trait.getDisplayName().replaceAll("\.", "_").replaceAll(" ", "__"); + + StaticTextItem item = new StaticTextItem(id, trait.getDisplayName()); + item.setTooltip(trait.getDescription()); + formItems.add(item); +// item.setValue("?"); + } + +// SectionItem section = new SectionItem("Summary", "Summary"); +// section.setTitle("Summary"); +// section.setDefaultValue("Summary"); +// section.setCanCollapse(true); +// section.setCellStyle("HidablePlainSectionHeader"); +// section.setItemIds(itemIds.toArray(new String[itemIds.size()])); +// formItems.add(0, section); + + formItems.add(new SpacerItem()); + setItems(formItems.toArray(new FormItem[formItems.size()])); + + setValue("type", type.getName() + " (" + type.getPlugin() + ")"); + setValue("name", resource.getName()); + setValue("description", resource.getDescription()); + setValue("location", resource.getLocation()); + setValue("version", (resource.getVersion() != null) ? resource.getVersion() : "<i>none</i>"); + Resource parentResource = resource.getParentResource(); + setValue("parent", parentResource != null ? + ("<a href="#Resource/" + parentResource.getId() + "">" + + parentResource.getName() + "</a>") : "<i>none</i>"); + } +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java index ac2abc2..2fff538 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/summary/OverviewView.java @@ -19,53 +19,35 @@ package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.summary;
import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumSet; import java.util.List;
-import com.google.gwt.user.client.rpc.AsyncCallback; -import com.smartgwt.client.util.SC; -import com.smartgwt.client.widgets.form.fields.FormItem; -import com.smartgwt.client.widgets.form.fields.HeaderItem; -import com.smartgwt.client.widgets.form.fields.SpacerItem; -import com.smartgwt.client.widgets.form.fields.StaticTextItem; - -import org.rhq.core.domain.measurement.DataType; -import org.rhq.core.domain.measurement.DisplayType; -import org.rhq.core.domain.measurement.MeasurementDataTrait; -import org.rhq.core.domain.measurement.MeasurementDefinition; import org.rhq.core.domain.resource.Resource; -import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.composite.ResourceComposite; -import org.rhq.enterprise.gui.coregui.client.CoreGUI; -import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedDynamicForm; -import org.rhq.enterprise.gui.coregui.client.components.form.TogglableTextItem; -import org.rhq.enterprise.gui.coregui.client.components.form.ValueUpdatedHandler; -import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; -import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync; import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceSelectListener; -import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository; -import org.rhq.enterprise.gui.coregui.client.util.message.Message; + +import com.smartgwt.client.util.SC; +import com.smartgwt.client.widgets.grid.ListGrid; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.grid.events.RecordClickEvent; +import com.smartgwt.client.widgets.grid.events.RecordClickHandler; +import com.smartgwt.client.widgets.layout.VLayout;
/** * The Resource Summary>Overview tab. * - * @author Greg Hinkle - * @author Ian Springer + * @author Lukas Krejci */ -public class OverviewView extends EnhancedDynamicForm implements ResourceSelectListener { +public class OverviewView extends VLayout implements ResourceSelectListener {
- private ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService(); private ResourceComposite resourceComposite;
- public OverviewView(ResourceComposite resourceComposite) { super(); this.resourceComposite = resourceComposite; }
- @Override protected void onDraw() { super.onDraw(); @@ -78,225 +60,43 @@ public class OverviewView extends EnhancedDynamicForm implements ResourceSelectL } }
- public void onResourceSelected(ResourceComposite resourceComposite) { - - this.resourceComposite = resourceComposite; - Resource resource = resourceComposite.getResource(); - - // Load metric defs. - ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(), - EnumSet.of(ResourceTypeRepository.MetadataType.measurements), - new ResourceTypeRepository.TypeLoadedCallback() { - public void onTypesLoaded(ResourceType type) { - try { - buildForm(type); - loadTraitValues(); - } catch (Exception e) { - SC.say("Form load failure"); - e.printStackTrace(); - } - } - }); + addMember(new OverviewForm(resourceComposite)); + ListGrid errorsGrid = buildErrorListGrid(resourceComposite); + if (errorsGrid != null) { + addMember(errorsGrid); + } }
- private void loadTraitValues() { + private static ListGrid buildErrorListGrid(ResourceComposite resourceComposite) { final Resource resource = resourceComposite.getResource(); - GWTServiceLookup.getMeasurementDataService().findCurrentTraitsForResource( - resource.getId(), - DisplayType.SUMMARY, - new AsyncCallback<List<MeasurementDataTrait>>() { - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError("Failed to load traits for " + resource + ".", - caught); - } - - public void onSuccess(List<MeasurementDataTrait> result) { - // TODO: Implement this method. - for (MeasurementDataTrait trait : result) { - String formId = trait.getName().replaceAll("\.", "_").replaceAll(" ", "__"); - FormItem item = getItem(formId); - - if (item != null) { - setValue(formId, trait.getValue()); - } - } - markForRedraw(); - } - } - ); - - } - - private void buildForm(ResourceType type) { - List<MeasurementDefinition> traits = new ArrayList<MeasurementDefinition>(); - - for (MeasurementDefinition measurement : type.getMetricDefinitions()) { - if (measurement.getDataType() == DataType.TRAIT && measurement.getDisplayType() == DisplayType.SUMMARY) { - traits.add(measurement); - } - } - - Collections.sort(traits, new Comparator<MeasurementDefinition>() { - public int compare(MeasurementDefinition o1, MeasurementDefinition o2) { - return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder()); - } - }); - - List<FormItem> formItems = new ArrayList<FormItem>(); - - HeaderItem headerItem = new HeaderItem("header", "Summary"); - headerItem.setValue("Summary"); - formItems.add(headerItem); + ListGrid errorsGrid = null; + if (resource.getResourceErrors() != null && resource.getResourceErrors().size() > 0) { + errorsGrid = new ListGrid();
- StaticTextItem typeItem = new StaticTextItem("type", "Type"); - typeItem.setTooltip("Plugin: " + type.getPlugin() + "\n<br>" + "Type: " + type.getName()); - typeItem.setValue(type.getName() + " (" + type.getPlugin() + ")"); - formItems.add(typeItem); + ListGridField summaryField = new ListGridField("summary", "Errors"); + summaryField.addRecordClickHandler(new RecordClickHandler() {
- final Resource resource = this.resourceComposite.getResource(); - boolean modifiable = this.resourceComposite.getResourcePermission().isInventory(); - - final FormItem nameItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); - nameItem.setName("name"); - nameItem.setTitle("Name"); - nameItem.setValue(resource.getName()); - if (nameItem instanceof TogglableTextItem) { - TogglableTextItem togglableNameItem = (TogglableTextItem) nameItem; - togglableNameItem.addValueUpdatedHandler(new ValueUpdatedHandler() { - public void onValueUpdated(final String newName) { - final String oldName = resource.getName(); - if (newName.equals(oldName)) { - return; - } - resource.setName(newName); - OverviewView.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError("Failed to change name of Resource with id " - + resource.getId() - + " from "" + oldName + "" to "" + newName + "".", caught); - // We failed to update it on the Server, so change back the Resource and the form item to - // the original value. - resource.setName(oldName); - nameItem.setValue(oldName); - } - - public void onSuccess(Void result) { - CoreGUI.getMessageCenter().notify(new Message("Name of Resource with id " - + resource.getId() + " was changed from "" - + oldName + "" to "" + newName + "".", Message.Severity.Info)); - } - }); + @Override + public void onRecordClick(RecordClickEvent event) { + String detail = event.getRecord().getAttribute("detail"); + SC.say("Error details", detail); } }); - } - formItems.add(nameItem); - - final FormItem descriptionItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); - descriptionItem.setName("description"); - descriptionItem.setTitle("Description"); - descriptionItem.setValue(resource.getDescription()); - if (descriptionItem instanceof TogglableTextItem) { - TogglableTextItem togglableDescriptionItem = (TogglableTextItem) descriptionItem; - togglableDescriptionItem.addValueUpdatedHandler(new ValueUpdatedHandler() { - public void onValueUpdated(final String newDescription) { - final String oldDescription = resource.getDescription(); - if (newDescription.equals(oldDescription)) { - return; - } - resource.setDescription(newDescription); - OverviewView.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError("Failed to change description of Resource with id " - + resource.getId() - + " from "" + oldDescription + "" to "" + newDescription + "".", caught); - // We failed to update it on the Server, so change back the Resource and the form item to - // the original value. - resource.setDescription(oldDescription); - descriptionItem.setValue(oldDescription); - } - - public void onSuccess(Void result) { - CoreGUI.getMessageCenter().notify(new Message("Description of Resource with id " - + resource.getId() + " was changed from "" - + oldDescription + "" to "" + newDescription + "".", Message.Severity.Info)); - } - }); - } - }); - } - formItems.add(descriptionItem);
- final FormItem locationItem = (modifiable) ? new TogglableTextItem() : new StaticTextItem(); - locationItem.setName("location"); - locationItem.setTitle("Location"); - locationItem.setValue(resource.getLocation()); - if (locationItem instanceof TogglableTextItem) { - TogglableTextItem togglableNameItem = (TogglableTextItem) locationItem; - togglableNameItem.addValueUpdatedHandler(new ValueUpdatedHandler() { - public void onValueUpdated(final String newLocation) { - final String oldLocation = resource.getLocation(); - if (newLocation.equals(oldLocation)) { - return; - } - resource.setLocation(newLocation); - OverviewView.this.resourceService.updateResource(resource, new AsyncCallback<Void>() { - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError("Failed to change location of Resource with id " - + resource.getId() - + " from "" + oldLocation + "" to "" + newLocation + "".", caught); - // We failed to update it on the Server, so change back the Resource and the form item to - // the original value. - resource.setLocation(oldLocation); - locationItem.setValue(oldLocation); - } + errorsGrid.setFields(summaryField);
- public void onSuccess(Void result) { - CoreGUI.getMessageCenter().notify(new Message("Location of Resource with id " - + resource.getId() + " was changed from "" - + oldLocation + "" to "" + newLocation + "".", Message.Severity.Info)); - } - }); - } - }); - } - formItems.add(locationItem); - - - StaticTextItem versionItem = new StaticTextItem("version", "Version"); - formItems.add(versionItem); - - StaticTextItem parentItem = new StaticTextItem("parent", "Parent"); - formItems.add(parentItem); - - for (MeasurementDefinition trait : traits) { - String id = trait.getDisplayName().replaceAll("\.", "_").replaceAll(" ", "__"); + List<ListGridRecord> errorList = new ArrayList<ListGridRecord>(); + for (ResourceError error : resource.getResourceErrors()) { + ListGridRecord record = new ListGridRecord(); + record.setAttribute("summary", error.getSummary()); + record.setAttribute("detail", error.getDetail()); + errorList.add(record); + }
- StaticTextItem item = new StaticTextItem(id, trait.getDisplayName()); - item.setTooltip(trait.getDescription()); - formItems.add(item); -// item.setValue("?"); + errorsGrid.setRecords(errorList.toArray(new ListGridRecord[errorList.size()])); }
-// SectionItem section = new SectionItem("Summary", "Summary"); -// section.setTitle("Summary"); -// section.setDefaultValue("Summary"); -// section.setCanCollapse(true); -// section.setCellStyle("HidablePlainSectionHeader"); -// section.setItemIds(itemIds.toArray(new String[itemIds.size()])); -// formItems.add(0, section); - - formItems.add(new SpacerItem()); - setItems(formItems.toArray(new FormItem[formItems.size()])); - - setValue("type", type.getName() + " (" + type.getPlugin() + ")"); - setValue("name", resource.getName()); - setValue("description", resource.getDescription()); - setValue("location", resource.getLocation()); - setValue("version", (resource.getVersion() != null) ? resource.getVersion() : "<i>none</i>"); - Resource parentResource = resource.getParentResource(); - setValue("parent", parentResource != null ? - ("<a href="#Resource/" + parentResource.getId() + "">" + - parentResource.getName() + "</a>") : "<i>none</i>"); + return errorsGrid; } }
commit d266142e299215832de65b40be45e40862f56128 Author: Lukas Krejci lkrejci@redhat.com Date: Fri Aug 20 15:14:04 2010 +0200
adding a test plugin that fails the upgrade so that we can add the tests for handling that scenario
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml index 4b4524a..a4ca249 100644 --- a/modules/core/plugin-container/pom.xml +++ b/modules/core/plugin-container/pom.xml @@ -177,6 +177,12 @@ <jar destfile="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar"> <fileset dir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v2" includes="*.class,**/rhq-plugin.xml" /> </jar> + <copy toDir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/failing/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/failing/rhq-plugin.xml" /> + </copy> + <jar destfile="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-3.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/failing" includes="*.class,**/rhq-plugin.xml" /> + </jar> </tasks> </configuration> <goals> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/DiscComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/DiscComponent.java new file mode 100644 index 0000000..54153e6 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/DiscComponent.java @@ -0,0 +1,54 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade.plugins.failing; + +import java.util.Collections; +import java.util.Set; + +import org.rhq.core.domain.resource.ResourceUpgradeReport; +import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails; +import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; + +/** + * + * @author Lukas Krejci + */ +public class DiscComponent implements ResourceDiscoveryComponent<ResourceComponent>, + ResourceUpgradeFacet<ResourceComponent> { + + private static final String RESOURCE_KEY = "resource-key-failing"; + private static final String RESOURCE_NAME = "resource-name-failing"; + private static final String RESOURCE_DESCRIPTION = "resource-description-failing"; + + public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent> context) + throws InvalidPluginConfigurationException, Exception { + return Collections.singleton(new DiscoveredResourceDetails(context.getResourceType(), RESOURCE_KEY, + RESOURCE_NAME, null, RESOURCE_DESCRIPTION, context.getDefaultPluginConfiguration(), null)); + } + + public ResourceUpgradeReport upgrade(ResourceUpgradeContext<ResourceComponent> inventoriedResource) { + throw new RuntimeException("Failing the upgrade purposefully."); + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/ResComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/ResComponent.java new file mode 100644 index 0000000..4c33adc --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/ResComponent.java @@ -0,0 +1,46 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade.plugins.failing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.rhq.core.domain.measurement.AvailabilityType; +import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceContext; + +/** + * + * @author Lukas Krejci + */ +public class ResComponent implements ResourceComponent<ResourceComponent> { + private static final Log log = LogFactory.getLog(ResComponent.class); + + public AvailabilityType getAvailability() { + return AvailabilityType.UP; + } + + public void start(ResourceContext<ResourceComponent> context) throws InvalidPluginConfigurationException, Exception { + log.info("~~~ starting the resource upgrade test failing component with resource key: " + context.getResourceKey()); + } + + public void stop() { + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/rhq-plugin.xml new file mode 100644 index 0000000..9e750d1 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/failing/rhq-plugin.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeTest" + displayName="Resource Upgrade Test" + description="Resource Upgrade Test" + package="org.rhq.core.pc.upgrade.plugins.failing" + version="3.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <server name="Resource" + discovery="DiscComponent" + class="ResComponent" + singleton="true" /> + +</plugin> +
commit 6dde2f7be37f23a5e8a9b25ccf66e99541fd3bc7 Merge: d58520e... 462e15f... Author: Lukas Krejci lkrejci@redhat.com Date: Fri Aug 20 12:50:39 2010 +0200
Merge branch 'master' into resource-upgrade
commit d58520e4a31ab38e03151e827488776d4dcca93f Author: Lukas Krejci lkrejci@redhat.com Date: Fri Aug 20 12:46:29 2010 +0200
Added agent and server side support for upgrade error reporting.
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java index f055e8c..9532920 100644 --- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java @@ -23,6 +23,9 @@
package org.rhq.core.clientapi.agent.upgrade;
+import java.io.PrintWriter; +import java.io.StringWriter; + import org.rhq.core.domain.resource.ResourceUpgradeReport;
/** @@ -34,44 +37,95 @@ public class ResourceUpgradeRequest extends ResourceUpgradeReport {
private static final long serialVersionUID = 1L;
- private int resourceId; + private final int resourceId; + private String upgradeErrorMessage; + private String upgradeErrorStackTrace; + private long timestamp;
- public ResourceUpgradeRequest() { - + public ResourceUpgradeRequest(int resourceId) { + this.resourceId = resourceId; }
public ResourceUpgradeRequest(int resourceId, ResourceUpgradeReport report) { - setResourceId(resourceId); - setNewDescription(report.getNewDescription()); - setNewName(report.getNewName()); - setNewResourceKey(report.getNewResourceKey()); + this.resourceId = resourceId; + fillInFromReport(report); } - + public int getResourceId() { return resourceId; }
- public void setResourceId(int resourceId) { - this.resourceId = resourceId; + public String getUpgradeErrorMessage() { + return upgradeErrorMessage; + } + + public void setUpgradeErrorMessage(String upgradeErrorMessage) { + this.upgradeErrorMessage = upgradeErrorMessage; + } + + public String getUpgradeErrorStackTrace() { + return upgradeErrorStackTrace; + } + + public void setUpgradeErrorStackTrace(String upgradeErrorStackTrace) { + this.upgradeErrorStackTrace = upgradeErrorStackTrace; + } + + public long getTimestamp() { + return timestamp; }
+ public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public void setErrorProperties(Throwable t) { + upgradeErrorMessage = t.getMessage(); + + StringWriter string = new StringWriter(); + PrintWriter w = new PrintWriter(string); + t.printStackTrace(w); + w.close(); + + upgradeErrorStackTrace = string.toString(); + } + + public void fillInFromReport(ResourceUpgradeReport report) { + setNewDescription(report.getNewDescription()); + setNewName(report.getNewName()); + setNewResourceKey(report.getNewResourceKey()); + } + + @Override + public boolean hasSomethingToUpgrade() { + return super.hasSomethingToUpgrade() || upgradeErrorMessage != null || upgradeErrorStackTrace != null; + } + @Override public int hashCode() { return 31 * resourceId; } - + @Override public boolean equals(Object other) { if (other == this) { return true; } - + if (!(other instanceof ResourceUpgradeRequest)) { return false; } - + ResourceUpgradeRequest r = (ResourceUpgradeRequest) other; - + return r.getResourceId() == resourceId; } + + @Override + public String toString() { + return "ResourceUpgradeRequest[resourceId = '" + resourceId + "', newResourceKey = '" + getNewResourceKey() + + "', newName = '" + getNewName() + "', newDescription = '" + getNewDescription() + + "', upgradeErrorMessage = '" + upgradeErrorMessage + "', upgradeErrorStackTrace = '" + + upgradeErrorStackTrace + "']"; + } } diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceErrorType.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceErrorType.java index 1435cc3..8fcedb7 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceErrorType.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceErrorType.java @@ -36,5 +36,10 @@ public enum ResourceErrorType { /** * An exception was thrown by the Resource component's getAvailablity() method the last time it was called. */ - AVAILABILITY_CHECK + AVAILABILITY_CHECK, + + /** + * There was an attempt to upgrade the resource on the agent but it failed. + */ + UPGRADE } \ No newline at end of file diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 728b2e3..3af9b84 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -1202,14 +1202,14 @@ public class InventoryManager extends AgentService implements ContainerService, return resourceContainer.updateAvailability(availabilityType); }
- public void mergeResourceFromUpgrade(Set<ResourceUpgradeRequest> upgradeReports) { + public void mergeResourceFromUpgrade(Set<ResourceUpgradeRequest> upgradeRequests) { Set<ResourceUpgradeResponse> serverUpdates = null; try { ServerServices serverServices = this.configuration.getServerServices(); if (serverServices != null) { DiscoveryServerService discoveryServerService = serverServices.getDiscoveryServerService();
- serverUpdates = discoveryServerService.upgradeResources(upgradeReports); + serverUpdates = discoveryServerService.upgradeResources(upgradeRequests); } } catch (Exception e) { log.error("Failed to process resource upgrades on the server.", e); diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java index 5b33fe1..025ba3a 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java @@ -82,12 +82,10 @@ public class ResourceUpgradeDelegate { * @return true if the resource was queued for upgrade, false otherwise * @throws PluginContainerException on error */ - public boolean processAndQueue(ResourceContainer resourceContainer) throws PluginContainerException { + public void processAndQueue(ResourceContainer resourceContainer) throws PluginContainerException { if (enabled) { - return executeResourceUpgradeFacetAndStoreRequest(resourceContainer); + executeResourceUpgradeFacetAndStoreRequest(resourceContainer); } - - return false; }
public void sendRequests() { @@ -100,7 +98,7 @@ public class ResourceUpgradeDelegate { }
@SuppressWarnings("unchecked") - private <T extends ResourceComponent> boolean executeResourceUpgradeFacetAndStoreRequest( + private <T extends ResourceComponent> void executeResourceUpgradeFacetAndStoreRequest( ResourceContainer resourceContainer) throws PluginContainerException {
ResourceComponent<T> parentResourceComponent = resourceContainer.getResourceContext() @@ -118,36 +116,47 @@ public class ResourceUpgradeDelegate {
if (!(discoveryComponent instanceof ResourceUpgradeFacet)) { //well, there's no point in continuing if the resource doesn't support the facet - return false; + return; }
ResourceUpgradeContext<ResourceComponent<T>> upgradeContext = inventoryManager.createResourceUpgradeContext( resource, parentResourceComponent, discoveryComponent);
- ResourceUpgradeReport upgradeReport; + ResourceUpgradeRequest request = new ResourceUpgradeRequest(resource.getId()); + + request.setTimestamp(System.currentTimeMillis()); + + ResourceUpgradeReport upgradeReport = null; try { upgradeReport = inventoryManager.invokeDiscoveryComponentResourceUpgradeFacet(resource.getResourceType(), discoveryComponent, upgradeContext); } catch (Throwable t) { log.error("ResourceUpgradeFacet threw an exception while upgrading resource [" + resource + "]", t); - return false; + request.setErrorProperties(t); }
- if (upgradeReport == null || !upgradeReport.hasSomethingToUpgrade()) { - return false; - } + if (upgradeReport != null && upgradeReport.hasSomethingToUpgrade()) { + String upgradeErrors = null; + if ((upgradeErrors = checkUpgradeValid(resource, upgradeReport)) != null) { + String errorString = "Upgrading the resource [" + resource + "] using these updates [" + upgradeReport + + "] would render the inventory invalid because of the following reasons: " + upgradeErrors; + + log.error(errorString); + + IllegalStateException ex = new IllegalStateException(errorString); + ex.fillInStackTrace(); + + request.setErrorProperties(ex); + } else { + request.fillInFromReport(upgradeReport); + }
- String upgradeErrors = null; - if ((upgradeErrors = checkUpgradeValid(resource, upgradeReport)) != null) { - log.error("Upgrading the resource [" + resource + "] using these updates [" + upgradeReport - + "] would render the inventory invalid because of the following reasons: " + upgradeErrors); - return false; }
//everything went ok, let's queue a upgrade request that will be sent to the server - requests.add(new ResourceUpgradeRequest(resource.getId(), upgradeReport)); - - return true; + if (request.hasSomethingToUpgrade()) { + requests.add(request); + } }
private String checkUpgradeValid(Resource resource, ResourceUpgradeReport upgradeReport) { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index 304cbad..b773384 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -58,6 +58,8 @@ import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.ProductVersion; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceCategory; +import org.rhq.core.domain.resource.ResourceError; +import org.rhq.core.domain.resource.ResourceErrorType; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.domain.util.PageControl; @@ -422,7 +424,9 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot Resource existingResource = this.entityManager.find(Resource.class, request.getResourceId()); if (existingResource != null) { ResourceUpgradeResponse upgradedData = upgradeResource(existingResource, request, allowGenericPropertiesUpgrade); - result.add(upgradedData); + if (upgradedData != null) { + result.add(upgradedData); + } } } return result; @@ -475,18 +479,24 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot
/** * @param existingResource - * @param upgradeReport + * @param upgradeRequest * @param allowGenericPropertiesUpgrade name and description are only upgraded if this is true * @return true if the resource was changed, false otherwise */ - private ResourceUpgradeResponse upgradeResource(@NotNull Resource resource, ResourceUpgradeReport upgradeReport, boolean allowGenericPropertiesUpgrade) { + private ResourceUpgradeResponse upgradeResource(@NotNull Resource resource, ResourceUpgradeRequest upgradeRequest, boolean allowGenericPropertiesUpgrade) { + if (upgradeRequest.getUpgradeErrorMessage() != null) { + ResourceError error = new ResourceError(resource, ResourceErrorType.UPGRADE, upgradeRequest.getUpgradeErrorMessage(), upgradeRequest.getUpgradeErrorStackTrace(), upgradeRequest.getTimestamp()); + entityManager.persist(error); + return null; + } + ResourceUpgradeResponse ret = new ResourceUpgradeResponse(); ret.setResourceId(resource.getId());
- String resourceKey = upgradeReport.getNewResourceKey(); - String name = upgradeReport.getNewName(); + String resourceKey = upgradeRequest.getNewResourceKey(); + String name = upgradeRequest.getNewName(); // String version = upgradeReport.getNewVersion(); - String description = upgradeReport.getNewDescription(); + String description = upgradeRequest.getNewDescription(); // Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); // Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration();
commit 5b093893923a739ed2634c73e05392e917b8e7fb Merge: 63d04ea... a13c17d... Author: Lukas Krejci lkrejci@redhat.com Date: Wed Aug 11 16:43:07 2010 +0200
Merge branch 'master' into resource-upgrade
diff --cc modules/enterprise/gui/portal-war/src/main/webapp/admin/config/GeneralPropertiesConfigForm.jsp index 136c37c,45526f7..0000000 deleted file mode 100644,100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/config/GeneralPropertiesConfigForm.jsp +++ /dev/null diff --cc modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index add8168,2773b4c..304cbad --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@@ -659,22 -559,10 +659,22 @@@ public class DiscoveryBossBean implemen */ ResourceType resourceType = resource.getResourceType(); Resource parent = resource; + Subject overlord = subjectManager.getOverlord(); while (parent != null && existingResource == null) { parent = parent.getParentResource(); - existingResource = resourceManager.getResourceByParentAndKey(subjectManager.getOverlord(), parent, + //check if the parent itself is inventoried. This might not be the case + //during initial sync-up for resource upgrade. + Resource existingParent = null; + if (parent != null) { + existingParent = entityManager.find(Resource.class, parent.getId()); + if (existingParent == null) { + //well, this parent is not known to the server, so there's no + //point in trying to find a child of it... + continue; + } + } + existingResource = resourceManager.getResourceByParentAndKey(overlord, existingParent, - resource.getResourceKey(), resourceType.getPlugin(), resourceType.getName()); + resource.getResourceKey(), resourceType.getPlugin(), resourceType.getName()); }
if (existingResource != null) { @@@ -905,8 -808,4 +920,8 @@@
updateInventoryStatus(subject, platforms, servers, target); } -} + + private static <T> boolean needsUpgrade(T oldValue, T newValue) { + return newValue != null && (oldValue == null || !newValue.equals(oldValue)); + } - } ++}
commit 63d04eaf7e697a241efe59832d7a4e127a084f92 Author: Lukas Krejci lkrejci@redhat.com Date: Mon Jul 12 18:39:22 2010 +0200
Adding tests for graceful handling of server-side exceptions and platform "disappearance" on the server-side.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index a5c3d1f..6fe7e96 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -940,8 +940,16 @@ public class InventoryManager extends AgentService implements ContainerService, //resource upgrade executor to sync up with the server side inventory *JUST AFTER* //this agent registered with the server for the very first time. In that case //the server hasn't received any info from us yet. + //Another (rare) scenario where this would happen would be when the platform resource type + //would change. + //In either case, let's sync up with the server - if it's got nothing, neither should the agent. if (syncInfo != null) { synchInventory(syncInfo); + } else { + purgeObsoleteResources(Collections.<String>emptySet()); + + //can't live without a platform, but we just deleted it. Let's rediscover it. + discoverPlatform(); }
return true; @@ -1077,8 +1085,10 @@ public class InventoryManager extends AgentService implements ContainerService, return; } boolean scan = removeResourceAndIndicateIfScanIsNeeded(resourceContainer.getResource()); - - if (scan) { + + //only actually schedule the scanning when we are finished with resource upgrade. The resource upgrade + //happens before any scanning infrastructure is established. + if (!resourceUpgradeDelegate.enabled() && scan) { log.info("Deleted resource #[" + resourceId + "] - this will trigger a server scan now"); inventoryThreadPoolExecutor.submit((Callable<InventoryReport>) this.serverScanExecutor); } @@ -2612,14 +2622,13 @@ public class InventoryManager extends AgentService implements ContainerService,
ResourceContainer container = getResourceContainer(resource); if (container != null) { - try { - container = getResourceContainer(resource); - resourceUpgradeDelegate.processAndQueue(container); - } catch (PluginContainerException e) { - log.error("Exception thrown while upgrading [" + resource + "]."); - } - if (container.getResourceComponentState() == ResourceComponentState.STARTED) { + try { + resourceUpgradeDelegate.processAndQueue(container); + } catch (PluginContainerException e) { + log.error("Exception thrown while upgrading [" + resource + "].", e); + } + for (Resource child : resource.getChildResources()) { upgradeResource(child); } diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java index c3bdbf4..19c1d95 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java @@ -56,7 +56,8 @@ public class FakeServerInventory { private Resource platform; private Map<String, Resource> resourceStore = new HashMap<String, Resource>(); private int counter; - + private boolean failing; + private static final Comparator<Resource> ID_COMPARATOR = new Comparator<Resource>() { public int compare(Resource o1, Resource o2) { return o1.getId() - o2.getId(); @@ -69,11 +70,21 @@ public class FakeServerInventory { } };
+ public FakeServerInventory() { + this(false); + } + + public FakeServerInventory(boolean failing) { + this.failing = failing; + } + //need to synchronize, because resource upgrade is async and can overlap with //resource discovery. public synchronized CustomAction mergeInventoryReport(final InventoryStatus requiredInventoryStatus) { return new CustomAction("updateServerSideInventory") { public Object invoke(Invocation invocation) throws Throwable { + throwIfFailing(); + InventoryReport inventoryReport = (InventoryReport) invocation.getParameter(0);
for(Resource res : inventoryReport.getAddedRoots()) { @@ -87,10 +98,24 @@ public class FakeServerInventory { }; }
+ public synchronized CustomAction clearPlatform() { + return new CustomAction("updateServerSideInventory - report platform deleted on the server") { + public Object invoke(Invocation invocation) throws Throwable { + throwIfFailing(); + + platform = null; + + return getSyncInfo(); + } + }; + } + public synchronized CustomAction upgradeResources() { return new CustomAction("upgradeServerSideInventory") { @SuppressWarnings({"serial", "unchecked"}) public Object invoke(Invocation invocation) throws Throwable { + throwIfFailing(); + Set<ResourceUpgradeRequest> requests = (Set<ResourceUpgradeRequest>) invocation.getParameter(0); Set<ResourceUpgradeResponse> responses = new HashSet<ResourceUpgradeResponse>();
@@ -129,6 +154,8 @@ public class FakeServerInventory { return new CustomAction("getResources") { @SuppressWarnings("unchecked") public Object invoke(Invocation invocation) throws Throwable { + throwIfFailing(); + Set<Integer> resourceIds = (Set<Integer>)invocation.getParameter(0); boolean includeDescendants = (Boolean) invocation.getParameter(1);
@@ -137,6 +164,14 @@ public class FakeServerInventory { }; }
+ public boolean isFailing() { + return failing; + } + + public void setFailing(boolean failing) { + this.failing = failing; + } + @SuppressWarnings("serial") public synchronized Set<Resource> findResourcesByType(final ResourceType type) { Set<Resource> result = new HashSet<Resource>(); @@ -218,6 +253,12 @@ public class FakeServerInventory { return platform != null ? convert(platform) : null; }
+ private void throwIfFailing() { + if (failing) { + throw new RuntimeException("Fake server inventory is in the failing mode."); + } + } + private static ResourceSyncInfo convert(Resource root) { try { ResourceSyncInfo ret = new ResourceSyncInfo(); diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index b5d571f..202e0c0 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -25,6 +25,7 @@ package org.rhq.core.pc.upgrade;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse;
import java.io.File; import java.io.IOException; @@ -151,11 +152,83 @@ public class ResourceUpgradeTest { }
@Test - public void testRecoveryWithServerUnavailable() throws Exception { - //TODO implement + public void testSkipUpgradeWhenServerUnavailable() throws Exception { + currentServerSideInventory = new FakeServerInventory(); + initialSyncAndDiscovery(InventoryStatus.COMMITTED); + + currentServerSideInventory.setFailing(true); + + TestPayload test = new TestPayload() { + public void test(Resource discoveredResource) { + assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); + assertEquals(discoveredResource.getName(), "resource-name-v1"); + assertEquals(discoveredResource.getDescription(), "resource-description-v1"); + } + + @SuppressWarnings("unchecked") + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + + between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); + will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + + never(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); + } + }; + } + }; + + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, test); + } + + @Test + public void testUpgradeWithPlatformDeletedOnServer() throws Exception { + currentServerSideInventory = new FakeServerInventory(); + initialSyncAndDiscovery(InventoryStatus.COMMITTED); + + TestPayload test = new TestPayload() { + public void test(Resource discoveredResource) { + assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); + assertEquals(discoveredResource.getName(), "resource-name-v2"); + assertEquals(discoveredResource.getDescription(), "resource-description-v2"); + + ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(discoveredResource); + File dataDir = container.getResourceContext().getDataDirectory(); + + File marker = new File(dataDir, "upgrade-succeeded"); + + assertFalse(marker.exists(), "The upgrade seems to have occured even though there shouldn't have been a resource to upgrade."); + } + + @SuppressWarnings("unchecked") + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + + //the first merge will be triggered from within the upgrade process and we are + //going to report null sync. + oneOf(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); + will(currentServerSideInventory.clearPlatform()); + + //the rest of the inventory merges are executed by discoveries, so let's import the + //discovered stuff into the server-side inventory. + between(1, 3).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); + will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + + never(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); + } + }; + } + }; + + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, test); }
private void initialSyncAndDiscovery(final InventoryStatus requiredInventoryStatus) throws Exception { + cleanDataDir(); executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), true, new TestPayload() { public void test(Resource discoveredResource) { assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); @@ -303,40 +376,43 @@ public class ResourceUpgradeTest { for(String pluginResourcePath : pluginResourcePaths) { copyPlugin(pluginResourcePath, pluginDir); } - + Mockery context = new Mockery(); - + PluginContainerConfiguration pcConfig = createPluginContainerConfiguration(context); - + if (clearInventoryDat) { File inventoryDat = new File(pcConfig.getDataDirectory(), "inventory.dat"); inventoryDat.delete(); } - + context.checking(test.getExpectations(context)); - + PluginContainer.getInstance().setConfiguration(pcConfig); PluginContainer.getInstance().initialize(); - - //give the pc the time to finish resource upgrade - Thread.sleep(1000); - - //execute full discovery - InventoryManager im = PluginContainer.getInstance().getInventoryManager(); - im.executeServerScanImmediately(); - im.executeServiceScanImmediately(); - - Set<Resource> resources = getTestingResources(); - - assertEquals(resources.size(), 1, "There should be only a single testing resource but " + resources + " were found."); - - Resource discoveredResource = resources.iterator().next(); - - test.test(discoveredResource); - - PluginContainer.getInstance().shutdown(); - - context.assertIsSatisfied(); + + try { + //give the pc the time to finish resource upgrade + Thread.sleep(1000); + + //execute full discovery + InventoryManager im = PluginContainer.getInstance().getInventoryManager(); + im.executeServerScanImmediately(); + im.executeServiceScanImmediately(); + + Set<Resource> resources = getTestingResources(); + + assertEquals(resources.size(), 1, "There should be only a single testing resource but " + resources + + " were found."); + + Resource discoveredResource = resources.iterator().next(); + + test.test(discoveredResource); + + context.assertIsSatisfied(); + } finally { + PluginContainer.getInstance().shutdown(); + } }
@SuppressWarnings("unchecked") @@ -356,4 +432,8 @@ public class ResourceUpgradeTest { expectations.allowing(currentDiscoveryServerService).getResources(expectations.with(Expectations.any(Set.class)), expectations.with(Expectations.any(boolean.class))); expectations.will(currentServerSideInventory.getResources()); } + + private void cleanDataDir() throws IOException { + FileUtils.cleanDirectory(new File(tmpDir, DATA_DIR_NAME)); + } }
commit 178d4de9fb18d7f9045e673e64c33a359436be81 Author: John Mazzitelli mazz@redhat.com Date: Tue Jul 6 19:12:26 2010 -0400
generate the two resource upgrade test plugins rather than have the .jar files committed directly to git this way we can see the source and change it if we ever need to. also allows us to have source to step through in a debugger
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml index 2e58102..93f64cf 100644 --- a/modules/core/plugin-container/pom.xml +++ b/modules/core/plugin-container/pom.xml @@ -126,6 +126,7 @@ <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> + <id>process-test-resources</id> <phase>process-test-resources</phase> <configuration> <tasks> @@ -151,7 +152,31 @@ <include name="**/lib/*" /> </fileset> </move> - <delete dir="${project.build.directory}/jboss-sigar/hyperic-sigar-${sigar.version}" /> + <delete dir="${project.build.directory}/jboss-sigar/hyperic-sigar-${sigar.version}" /> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + <execution> + <id>process-test-classes</id> + <phase>process-test-classes</phase> + <configuration> + <tasks> + <echo>Assembling the two resource upgrade test plugins</echo> + <copy toDir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v1/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/v1/rhq-plugin.xml" /> + </copy> + <jar destfile="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-1.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v1" includes="*.class,**/rhq-plugin.xml" /> + </jar> + <copy toDir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v2/META-INF"> + <fileset file="${project.build.testSourceDirectory}/org/rhq/core/pc/upgrade/plugins/v2/rhq-plugin.xml" /> + </copy> + <jar destfile="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar"> + <fileset dir="${project.build.testOutputDirectory}/org/rhq/core/pc/upgrade/plugins/v2" includes="*.class,**/rhq-plugin.xml" /> + </jar> </tasks> </configuration> <goals> diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/DiscComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/DiscComponent.java new file mode 100644 index 0000000..5fbca32 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/DiscComponent.java @@ -0,0 +1,22 @@ +package org.rhq.core.pc.upgrade.plugins.v1; + +import java.util.Collections; +import java.util.Set; + +import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails; +import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; + +public class DiscComponent implements ResourceDiscoveryComponent<ResourceComponent> { + private static final String RESOURCE_KEY = "resource-key-v1"; + private static final String RESOURCE_NAME = "resource-name-v1"; + private static final String RESOURCE_DESCRIPTION = "resource-description-v1"; + + public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent> context) + throws InvalidPluginConfigurationException, Exception { + return Collections.singleton(new DiscoveredResourceDetails(context.getResourceType(), RESOURCE_KEY, + RESOURCE_NAME, null, RESOURCE_DESCRIPTION, context.getDefaultPluginConfiguration(), null)); + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/ResComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/ResComponent.java new file mode 100644 index 0000000..cc21fc3 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/ResComponent.java @@ -0,0 +1,21 @@ +package org.rhq.core.pc.upgrade.plugins.v1; + +import org.apache.commons.logging.LogFactory; + +import org.rhq.core.domain.measurement.AvailabilityType; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceContext; + +public class ResComponent implements ResourceComponent<ResourceComponent> { + public AvailabilityType getAvailability() { + return AvailabilityType.UP; + } + + public void start(ResourceContext<ResourceComponent> context) { + LogFactory.getLog(this.getClass()).info( + "~~~ Starting resource upgrade test plugin v1 component: key=" + context.getResourceKey()); + } + + public void stop() { + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/rhq-plugin.xml new file mode 100644 index 0000000..c658e0c --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v1/rhq-plugin.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeTest" + displayName="Resource Upgrade Test" + description="Resource Upgrade Test" + package="org.rhq.core.pc.upgrade.plugins.v1" + version="1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <server name="Resource" + discovery="DiscComponent" + class="ResComponent" + singleton="true" /> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/DiscComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/DiscComponent.java new file mode 100644 index 0000000..d113d1c --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/DiscComponent.java @@ -0,0 +1,54 @@ +package org.rhq.core.pc.upgrade.plugins.v2; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.Set; + +import org.rhq.core.domain.resource.ResourceUpgradeReport; +import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails; +import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; + +public class DiscComponent implements ResourceDiscoveryComponent<ResourceComponent>, + ResourceUpgradeFacet<ResourceComponent> { + private static final String V1_RESOURCE_KEY = "resource-key-v1"; + private static final String RESOURCE_KEY = "resource-key-v2"; + private static final String RESOURCE_NAME = "resource-name-v2"; + private static final String RESOURCE_DESCRIPTION = "resource-description-v2"; + + public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent> context) + throws InvalidPluginConfigurationException, Exception { + return Collections.singleton(new DiscoveredResourceDetails(context.getResourceType(), RESOURCE_KEY, + RESOURCE_NAME, null, RESOURCE_DESCRIPTION, context.getDefaultPluginConfiguration(), null)); + } + + public ResourceUpgradeReport upgrade(ResourceUpgradeContext<ResourceComponent> inventoriedResource) { + if (V1_RESOURCE_KEY.equals(inventoriedResource.getResourceKey())) { + ResourceUpgradeReport report = new ResourceUpgradeReport(); + report.setNewResourceKey(RESOURCE_KEY); + report.setNewName(RESOURCE_NAME); + report.setNewDescription(RESOURCE_DESCRIPTION); + + File dataDir = inventoriedResource.getDataDirectory(); + + if (dataDir != null) { + if (!(dataDir.exists())) { + dataDir.mkdir(); + } + File marker = new File(dataDir, "upgrade-succeeded"); + try { + marker.createNewFile(); + } catch (IOException localIOException) { + } + } + return report; + } + + return null; + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/ResComponent.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/ResComponent.java new file mode 100644 index 0000000..83144b2 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/ResComponent.java @@ -0,0 +1,21 @@ +package org.rhq.core.pc.upgrade.plugins.v2; + +import org.apache.commons.logging.LogFactory; + +import org.rhq.core.domain.measurement.AvailabilityType; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceContext; + +public class ResComponent implements ResourceComponent<ResourceComponent> { + public AvailabilityType getAvailability() { + return AvailabilityType.UP; + } + + public void start(ResourceContext<ResourceComponent> context) { + LogFactory.getLog(this.getClass()).info( + "~~~ Starting resource upgrade test plugin v2 component: key=" + context.getResourceKey()); + } + + public void stop() { + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/rhq-plugin.xml b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/rhq-plugin.xml new file mode 100644 index 0000000..9f63892 --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/plugins/v2/rhq-plugin.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin name="ResourceUpgradeTest" + displayName="Resource Upgrade Test" + description="Resource Upgrade Test" + package="org.rhq.core.pc.upgrade.plugins.v2" + version="2.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="urn:xmlns:rhq-plugin" + xmlns:c="urn:xmlns:rhq-configuration"> + + <server name="Resource" + discovery="DiscComponent" + class="ResComponent" + singleton="true" /> + +</plugin> + diff --git a/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-1.0.0.jar b/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-1.0.0.jar deleted file mode 100644 index 33a79c0..0000000 Binary files a/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-1.0.0.jar and /dev/null differ diff --git a/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar b/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar deleted file mode 100644 index 7ffc5bb..0000000 Binary files a/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar and /dev/null differ
commit 9edde408d4dbabbc057e5e11fdfb6c3c16d2936e Author: John Mazzitelli mazz@redhat.com Date: Tue Jul 6 16:11:44 2010 -0400
trivial - reformat some things. no need to use isDebugEnabled if you are logging a simple string message with no string concatentation
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 5786702..a5c3d1f 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -72,8 +72,8 @@ import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.ResourceCreationDataType; import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.ResourceErrorType; -import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.pc.ContainerService; import org.rhq.core.pc.PluginContainer; import org.rhq.core.pc.PluginContainerConfiguration; @@ -193,7 +193,7 @@ public class InventoryManager extends AgentService implements ContainerService, * Handles the resource upgrade during the initialization of the inventory manager. */ private ResourceUpgradeDelegate resourceUpgradeDelegate; - + public InventoryManager() { super(DiscoveryAgentService.class); } @@ -224,7 +224,7 @@ public class InventoryManager extends AgentService implements ContainerService, //discoveries. resourceUpgradeDelegate = new ResourceUpgradeDelegate(this); upgradeResources(); - + availabilityCollectors = new AvailabilityCollectorThreadPool(); availabilityCollectors.initialize();
@@ -300,7 +300,7 @@ public class InventoryManager extends AgentService implements ContainerService, return results; } catch (TimeoutException te) { log.warn("Discovery for Resources of [" + context.getResourceType() + "] has been running for more than " - + timeout + " milliseconds. This may be a plugin bug.", te); + + timeout + " milliseconds. This may be a plugin bug.", te); return null; } catch (BlacklistedException be) { // Discovery did not run, because the ResourceType was blacklisted during a prior discovery scan. @@ -333,8 +333,8 @@ public class InventoryManager extends AgentService implements ContainerService, return result; } catch (TimeoutException te) { log.warn("Manual add of Resource of type [" + context.getResourceType() + "] with plugin configuration [" - + pluginConfig.toString(true) + "] has been running for more than " - + timeout + " milliseconds. This may be a plugin bug.", te); + + pluginConfig.toString(true) + "] has been running for more than " + timeout + + " milliseconds. This may be a plugin bug.", te); return null; } catch (BlacklistedException be) { log.debug(ThrowableUtil.getAllMessages(be)); @@ -382,11 +382,12 @@ public class InventoryManager extends AgentService implements ContainerService, public <T extends ResourceComponent> ResourceUpgradeReport invokeDiscoveryComponentResourceUpgradeFacet( ResourceType resourceType, ResourceDiscoveryComponent<T> component, ResourceUpgradeContext<T> inventoriedResource) throws Throwable { - + long timeout = getDiscoveryComponentTimeout(resourceType); try { @SuppressWarnings("unchecked") - ResourceUpgradeFacet<T> proxy = this.discoveryComponentProxyFactory.getDiscoveryComponentProxy(resourceType, component, timeout, ResourceUpgradeFacet.class); + ResourceUpgradeFacet<T> proxy = this.discoveryComponentProxyFactory.getDiscoveryComponentProxy( + resourceType, component, timeout, ResourceUpgradeFacet.class);
return proxy.upgrade(inventoriedResource); } catch (BlacklistedException e) { @@ -394,7 +395,7 @@ public class InventoryManager extends AgentService implements ContainerService, return null; } } - + public DiscoveryComponentProxyFactory getDiscoveryComponentProxyFactory() { return this.discoveryComponentProxyFactory; } @@ -892,7 +893,7 @@ public class InventoryManager extends AgentService implements ContainerService, public boolean handleReport(InventoryReport report) { return handleReport(report, false); } - + /** * Send an inventory report to the Server. * @@ -904,7 +905,7 @@ public class InventoryManager extends AgentService implements ContainerService, if (!configuration.isInsideAgent()) { return true; } - + if (report.getAddedRoots().isEmpty() && !forceServerRoundtrip) { return true; // nothing to do } @@ -981,7 +982,7 @@ public class InventoryManager extends AgentService implements ContainerService, log.debug(String.format("DONE syncing local inventory [%d] ms.", (System.currentTimeMillis() - startTime))); } - + // If we synced any Resources, one or more Resource components were probably started, // so run an avail check to report on their availabilities immediately. Also kick off // a service scan to scan those Resources for new child Resources. Kick both tasks off @@ -991,7 +992,8 @@ public class InventoryManager extends AgentService implements ContainerService, // inventory with the server side as well as to disallow any other server-agent traffic during // the upgrade phase. Not to mention the fact that no thread pools are initialized yet by the // time the upgrade kicks in.. - if (!resourceUpgradeDelegate.enabled() && (!syncedResources.isEmpty() || !unknownResourceIds.isEmpty() || !modifiedResourceIds.isEmpty())) { + if (!resourceUpgradeDelegate.enabled() + && (!syncedResources.isEmpty() || !unknownResourceIds.isEmpty() || !modifiedResourceIds.isEmpty())) { performAvailabilityChecks(true); this.inventoryThreadPoolExecutor.schedule((Callable<? extends Object>) this.serviceScanExecutor, 5, TimeUnit.SECONDS); @@ -1003,7 +1005,7 @@ public class InventoryManager extends AgentService implements ContainerService, throw new RuntimeException(t); } } - + private void getAllUuids(ResourceSyncInfo syncInfo, Set<String> allServerSideUuids) { allServerSideUuids.add(syncInfo.getUuid()); for (ResourceSyncInfo child : syncInfo.getChildSyncInfos()) { @@ -1181,13 +1183,13 @@ public class InventoryManager extends AgentService implements ContainerService, ServerServices serverServices = this.configuration.getServerServices(); if (serverServices != null) { DiscoveryServerService discoveryServerService = serverServices.getDiscoveryServerService(); - + serverUpdates = discoveryServerService.upgradeResources(upgradeReports); } } catch (Exception e) { log.error("Failed to process resource upgrades on the server.", e); } - + if (serverUpdates != null) { for (ResourceUpgradeResponse upgradeResponse : serverUpdates) { String resourceKey = upgradeResponse.getUpgradedResourceKey(); @@ -1202,49 +1204,50 @@ public class InventoryManager extends AgentService implements ContainerService, ResourceContainer existingResourceContainer = getResourceContainer(upgradeResponse.getResourceId()); if (existingResourceContainer != null) { Resource existingResource = existingResourceContainer.getResource(); - - StringBuilder logMessage = new StringBuilder("Resource [") - .append(existingResource.toString()).append("] upgraded its "); - + + StringBuilder logMessage = new StringBuilder("Resource [").append(existingResource.toString()) + .append("] upgraded its "); + if (resourceKey != null) { existingResource.setResourceKey(resourceKey); logMessage.append("resourceKey, "); } - + if (name != null) { existingResource.setName(name); logMessage.append("name, "); } - -// if (version != null) { -// existingResource.setVersion(version); -// } - + + //if (version != null) { + // existingResource.setVersion(version); + //} + if (description != null) { existingResource.setDescription(description); logMessage.append("description, "); } - -// if (pluginConfiguration != null) { -// existingResource.setPluginConfiguration(pluginConfiguration); -// } -// -// if (resourceConfiguration != null) { -// existingResource.setResourceConfiguration(resourceConfiguration); -// } - - logMessage.replace(logMessage.length() - 1, logMessage.length(), - "to become [").append(existingResource.toString()).append("]"); - + + //if (pluginConfiguration != null) { + // existingResource.setPluginConfiguration(pluginConfiguration); + //} + // + //if (resourceConfiguration != null) { + // existingResource.setResourceConfiguration(resourceConfiguration); + //} + + logMessage.replace(logMessage.length() - 1, logMessage.length(), "to become [").append( + existingResource.toString()).append("]"); + log.info(logMessage.toString()); } else { - log.error("Upgraded a resource that is not present on the agent. This should not happen. The id of the missing resource is " + upgradeResponse.getResourceId()); + log.error("Upgraded a resource that is not present on the agent. This should not happen. " + + "The id of the missing resource is: " + upgradeResponse.getResourceId()); } } } } } - + public Resource mergeResourceFromDiscovery(Resource resource, Resource parent) throws PluginContainerException { // If the Resource is already in inventory, make sure its version is up-to-date, then simply return the // existing Resource. @@ -1466,7 +1469,7 @@ public class InventoryManager extends AgentService implements ContainerService, }
ResourceContext context = createResourceContext(resource, parentComponent, discoveryComponent); - + container.setResourceContext(context);
// Wrap the component in a proxy that will provide locking and a timeout for the call to start(). @@ -1513,7 +1516,8 @@ public class InventoryManager extends AgentService implements ContainerService, } }
- private <T extends ResourceComponent> ResourceContext<T> createResourceContext(Resource resource, T parentComponent, ResourceDiscoveryComponent<T> discoveryComponent) { + private <T extends ResourceComponent> ResourceContext<T> createResourceContext(Resource resource, + T parentComponent, ResourceDiscoveryComponent<T> discoveryComponent) { File pluginDataDir = new File(this.configuration.getDataDirectory(), resource.getResourceType().getPlugin());
return new ResourceContext<T>(resource, // the resource itself @@ -1529,8 +1533,9 @@ public class InventoryManager extends AgentService implements ContainerService, this.availabilityCollectors, // for components that want to perform async avail checking this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do } - - public <T extends ResourceComponent> ResourceUpgradeContext<T> createResourceUpgradeContext(Resource resource, T parentComponent, ResourceDiscoveryComponent<T> discoveryComponent) { + + public <T extends ResourceComponent> ResourceUpgradeContext<T> createResourceUpgradeContext(Resource resource, + T parentComponent, ResourceDiscoveryComponent<T> discoveryComponent) { File pluginDataDir = new File(this.configuration.getDataDirectory(), resource.getResourceType().getPlugin());
return new ResourceUpgradeContext<T>(resource, // the resource itself @@ -1546,7 +1551,7 @@ public class InventoryManager extends AgentService implements ContainerService, this.availabilityCollectors, // for components that want to perform async avail checking this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do } - + /** * This will send a resource error to the server (if applicable) to indicate that the given resource could not be * connected to due to an invalid plugin configuration. @@ -1789,13 +1794,13 @@ public class InventoryManager extends AgentService implements ContainerService, Set<DiscoveredResourceDetails> allDiscoveredPlatforms = new HashSet<DiscoveredResourceDetails>(2);
if ((platformTypes != null) && (platformTypes.size() > 0)) { - + //check for fake testing type. If the test platform type is being used, it is always going to be //the sole platform type available. if (platformTypes.size() == 1 && platformTypes.contains(PluginMetadataManager.TEST_PLATFORM_TYPE)) { return getTestPlatform(); } - + // Go through all the platform types that are supported and see if they can detect our platform. for (ResourceType platformType : platformTypes) { try { @@ -2123,11 +2128,11 @@ public class InventoryManager extends AgentService implements ContainerService, @NotNull Set<Resource> executeComponentDiscovery(ResourceType resourceType, ResourceDiscoveryComponent discoveryComponent, ResourceContainer parentContainer, List<ProcessScanResult> processScanResults) { - + ResourceContext parentResourceContext = parentContainer.getResourceContext(); ResourceComponent parentComponent = parentContainer.getResourceComponent(); Resource parentResource = parentContainer.getResource(); - + long startTime = System.currentTimeMillis(); log.debug("Executing discovery for [" + resourceType.getName() + "] Resources..."); Set<Resource> newResources; @@ -2578,9 +2583,7 @@ public class InventoryManager extends AgentService implements ContainerService,
private void upgradeResources() { try { - if (log.isDebugEnabled()) { - log.debug("Executing resource upgrade."); - } + log.debug("Executing resource upgrade.");
boolean syncResult = handleReport(new InventoryReport(getAgent()), true); if (!syncResult) { @@ -2590,27 +2593,23 @@ public class InventoryManager extends AgentService implements ContainerService,
upgradeResource(getPlatform());
- if (log.isDebugEnabled()) { - log.debug("Sending the upgrade requests to the server."); - } + log.debug("Sending the upgrade requests to the server."); resourceUpgradeDelegate.sendRequests();
resourceUpgradeDelegate.disable();
- if (log.isDebugEnabled()) { - log.debug("Resource upgrade finished."); - } + log.debug("Resource upgrade finished."); } catch (Throwable t) { log.error("Resource upgrade failed with an exception.", t); } } - + private void upgradeResource(Resource resource) { //only process committed resources if (resource.getInventoryStatus() != InventoryStatus.COMMITTED) { return; } - + ResourceContainer container = getResourceContainer(resource); if (container != null) { try { @@ -2625,14 +2624,15 @@ public class InventoryManager extends AgentService implements ContainerService, upgradeResource(child); } } else { - log.error("The resource container for resource [" + resource + "] wasn't started during upgrade. This should not happen."); - } + log.error("The resource container for resource [" + resource + + "] wasn't started during upgrade. This should not happen."); + } } else { log.error("Resource container not initialized for resource [" + resource + "] during upgrade. This should not happen."); } } - + /** * That class implements a listener that gets called when the resource got activated * @author hrupp
commit 1e41a098af78a7d97e0a0415dba48bf0b98dba73 Author: John Mazzitelli mazz@redhat.com Date: Tue Jul 6 16:03:35 2010 -0400
trivial - add comment, small reformat
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java index cb466bd..5b33fe1 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java @@ -24,6 +24,7 @@ import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.rhq.core.clientapi.agent.PluginContainerException; import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; import org.rhq.core.domain.resource.Resource; @@ -40,6 +41,11 @@ import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; * This is a helper class to {@link InventoryManager} that takes care of resource upgrade. * Note that this class is not thread-safe in any manner. * + * This class must not call (explicitly or implicitly anywhere in its outgoing call chain) + * any other plugin container manager other than the InventoryManager. This is because + * this delegate is called within the Inventory Manager's initialize method and hence + * many other managers are not yet initialized themselves yet. + * * @author Lukas Krejci */ public class ResourceUpgradeDelegate { @@ -62,7 +68,7 @@ public class ResourceUpgradeDelegate { public boolean enabled() { return enabled; } - + /** * Disables all future operations of the delegate. */ @@ -93,10 +99,10 @@ public class ResourceUpgradeDelegate { } }
+ @SuppressWarnings("unchecked") private <T extends ResourceComponent> boolean executeResourceUpgradeFacetAndStoreRequest( ResourceContainer resourceContainer) throws PluginContainerException {
- @SuppressWarnings("unchecked") ResourceComponent<T> parentResourceComponent = resourceContainer.getResourceContext() .getParentResourceComponent();
@@ -107,7 +113,6 @@ public class ResourceUpgradeDelegate {
Resource resource = resourceContainer.getResource();
- @SuppressWarnings("unchecked") ResourceDiscoveryComponent<ResourceComponent<T>> discoveryComponent = PluginContainer.getInstance() .getPluginComponentFactory().getDiscoveryComponent(resource.getResourceType(), parentResourceContainer);
@@ -146,13 +151,13 @@ public class ResourceUpgradeDelegate { }
private String checkUpgradeValid(Resource resource, ResourceUpgradeReport upgradeReport) { - StringBuilder bld = new StringBuilder(); + StringBuilder s = new StringBuilder();
if (!checkResourceKeyUniqueAmongSiblings(resource, upgradeReport)) { - bld.append("\nAnother inventoried sibling resource of the same type already has the proposed resource key."); + s.append("\nAnother inventoried sibling resource of the same type already has the proposed resource key."); }
- return bld.length() > 0 ? bld.toString() : null; + return s.length() > 0 ? s.toString() : null; }
private boolean checkResourceKeyUniqueAmongSiblings(Resource resource, ResourceUpgradeReport upgradeReport) {
commit fb7c05447b2b4d0f3ebf30481942f12d176f759e Author: John Mazzitelli mazz@redhat.com Date: Tue Jul 6 16:02:39 2010 -0400
trivial - remove tabs
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java index d122da4..915a9e7 100644 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java @@ -35,12 +35,11 @@ import org.rhq.core.pluginapi.inventory.ResourceComponent; * @author Lukas Krejci */ public interface ResourceUpgradeFacet<T extends ResourceComponent> { - - /** - * Specifies what data should change on the provided resource to upgrade it to the current version. - * - * @param inventoriedResource a context representing the resource to be upgraded - * @return a report specifying what aspects of the resource should be changed or null if there is nothing to upgrade - */ - ResourceUpgradeReport upgrade(ResourceUpgradeContext<T> inventoriedResource); + /** + * Specifies what data should change on the provided resource to upgrade it to the current version. + * + * @param inventoriedResource a context representing the resource to be upgraded + * @return a report specifying what aspects of the resource should be changed or null if there is nothing to upgrade + */ + ResourceUpgradeReport upgrade(ResourceUpgradeContext<T> inventoriedResource); }
commit 18316510cafe27425cd1ac3cc1d08afe398d77ab Merge: 14db66f... fac71cd... Author: Lukas Krejci lkrejci@redhat.com Date: Fri Jul 2 17:54:08 2010 +0200
Merge branch 'release-3.0.0' into resource-upgrade
commit 14db66fe1f2774bcead24daebee947e6b52851dd Author: Lukas Krejci lkrejci@redhat.com Date: Fri Jul 2 17:52:12 2010 +0200
Refactoring the resource upgrade to upgrade before the discovery during InventoryManager.initialize(). That enables us to remove all the synchronization on the resources.
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java index 825a616..f055e8c 100644 --- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java @@ -32,6 +32,8 @@ import org.rhq.core.domain.resource.ResourceUpgradeReport; */ public class ResourceUpgradeRequest extends ResourceUpgradeReport {
+ private static final long serialVersionUID = 1L; + private int resourceId;
public ResourceUpgradeRequest() { @@ -52,4 +54,24 @@ public class ResourceUpgradeRequest extends ResourceUpgradeReport { public void setResourceId(int resourceId) { this.resourceId = resourceId; } + + @Override + public int hashCode() { + return 31 * resourceId; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof ResourceUpgradeRequest)) { + return false; + } + + ResourceUpgradeRequest r = (ResourceUpgradeRequest) other; + + return r.getResourceId() == resourceId; + } } diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java index 0f9db04..c2bc392 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java @@ -108,4 +108,14 @@ public class ResourceUpgradeReport implements Serializable { public void setNewDescription(String newDescription) { this.newDescription = newDescription; } + + public boolean hasSomethingToUpgrade() { + return newResourceKey != null || + newName != null || + newDescription != null; + } + + public String toString() { + return "ResourceUpgradeReport[newResourceKey = '" + newResourceKey + "', newName = '" + newName + "', newDescription = '" + newDescription + "']"; + } } diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java index 914641c..d122da4 100644 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java @@ -23,9 +23,6 @@
package org.rhq.core.pluginapi.upgrade;
-import java.util.Map; -import java.util.Set; - import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.pluginapi.inventory.ResourceComponent;
@@ -39,19 +36,11 @@ import org.rhq.core.pluginapi.inventory.ResourceComponent; */ public interface ResourceUpgradeFacet<T extends ResourceComponent> {
- /** - * This method is called on the discovery component straight after it has finished the discovery. - * The exact same discovery results are passed to this method along with the set of resources - * that already exist in the inventory. - * - * @param inventoriedSiblings the existing resources - * @param parentContext the parent of both the newly discovered and existing resources - * @param discoveryResults the discovered resources. The resources from this set that have - * the same resource key as one of the inventoried siblings (after upgrade using the results of this method) won't - * be reported. - * @return the mapping of old resources to the newly desired data. The keys are instances from the - * inventoriedSiblings set, the values are the upgrade reports detailing what the data of the - * corresponding siblings should be upgraded to. - */ - Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext<T>> inventoriedSiblings, ResourceUpgradeContext<? extends ResourceComponent> parentContext, Set<ResourceUpgradeContext<T>> discoveryResults); + /** + * Specifies what data should change on the provided resource to upgrade it to the current version. + * + * @param inventoriedResource a context representing the resource to be upgraded + * @return a report specifying what aspects of the resource should be changed or null if there is nothing to upgrade + */ + ResourceUpgradeReport upgrade(ResourceUpgradeContext<T> inventoriedResource); } diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java index 4d61e93..7561bf7 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java @@ -261,10 +261,6 @@ public class PluginContainer implements ContainerService { } finally { releaseLock(lock); } - - //fire off the resource upgrade as soon as possible. It will run only once per plugin container - //lifetime. - inventoryManager.fireResourceUpgrade();
return; } diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index ee42f7d..5786702 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -33,11 +33,9 @@ import java.util.IdentityHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Queue; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -93,8 +91,7 @@ import org.rhq.core.pc.plugin.BlacklistedException; import org.rhq.core.pc.plugin.CanonicalResourceKey; import org.rhq.core.pc.plugin.PluginComponentFactory; import org.rhq.core.pc.plugin.PluginManager; -import org.rhq.core.pc.upgrade.ResourceUpgradeExecutor; -import org.rhq.core.pc.upgrade.ResourceUpgradePendingRequest; +import org.rhq.core.pc.upgrade.ResourceUpgradeDelegate; import org.rhq.core.pc.util.DiscoveryComponentProxyFactory; import org.rhq.core.pc.util.FacetLockType; import org.rhq.core.pc.util.LoggingThreadFactory; @@ -195,7 +192,7 @@ public class InventoryManager extends AgentService implements ContainerService, /** * Handles the resource upgrade during the initialization of the inventory manager. */ - private ResourceUpgradeExecutor resourceUpgradeExecutor; + private ResourceUpgradeDelegate resourceUpgradeDelegate;
public InventoryManager() { super(DiscoveryAgentService.class); @@ -219,12 +216,18 @@ public class InventoryManager extends AgentService implements ContainerService, loadFromDisk(); }
- availabilityCollectors = new AvailabilityCollectorThreadPool(); - availabilityCollectors.initialize(); - // Discover the platform first thing. executePlatformScan();
+ //try the resource upgrade before we have any schedulers set up + //so that we don't get any interventions from concurrently running + //discoveries. + resourceUpgradeDelegate = new ResourceUpgradeDelegate(this); + upgradeResources(); + + availabilityCollectors = new AvailabilityCollectorThreadPool(); + availabilityCollectors.initialize(); + // Never run more than one avail check at a time. availabilityThreadPoolExecutor = new ScheduledThreadPoolExecutor(AVAIL_THREAD_POOL_CORE_POOL_SIZE, new LoggingThreadFactory(AVAIL_THREAD_POOL_NAME, true)); @@ -251,8 +254,6 @@ public class InventoryManager extends AgentService implements ContainerService, inventoryThreadPoolExecutor.scheduleWithFixedDelay(serviceScanExecutor, configuration .getServiceDiscoveryInitialDelay(), configuration.getServiceDiscoveryPeriod(), TimeUnit.SECONDS); } - - resourceUpgradeExecutor = new ResourceUpgradeExecutor(this); } finally { inventoryLock.writeLock().unlock(); } @@ -378,20 +379,19 @@ public class InventoryManager extends AgentService implements ContainerService, return results; }
- public <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> invokeDiscoveryComponentResourceUpgradeFacet( + public <T extends ResourceComponent> ResourceUpgradeReport invokeDiscoveryComponentResourceUpgradeFacet( ResourceType resourceType, ResourceDiscoveryComponent<T> component, - Set<ResourceUpgradeContext<T>> inventoriedSiblings, ResourceUpgradeContext<?> parent, - Set<ResourceUpgradeContext<T>> discoveredResources) throws Throwable { + ResourceUpgradeContext<T> inventoriedResource) throws Throwable {
long timeout = getDiscoveryComponentTimeout(resourceType); try { @SuppressWarnings("unchecked") ResourceUpgradeFacet<T> proxy = this.discoveryComponentProxyFactory.getDiscoveryComponentProxy(resourceType, component, timeout, ResourceUpgradeFacet.class);
- return proxy.upgrade(inventoriedSiblings, parent, discoveredResources); + return proxy.upgrade(inventoriedResource); } catch (BlacklistedException e) { log.debug(e); - return Collections.emptyMap(); + return null; } }
@@ -518,15 +518,6 @@ public class InventoryManager extends AgentService implements ContainerService, } }
- /** - * Executes the resource upgrade asynchronously. - */ - public void fireResourceUpgrade() { - Thread resourceUpgradeThread = new Thread(resourceUpgradeExecutor, "Resource Upgrade Thread"); - resourceUpgradeThread.setDaemon(true); - resourceUpgradeThread.start(); - } - public InventoryReport executeServerScanImmediately() { try { return inventoryThreadPoolExecutor.submit((Callable<InventoryReport>) this.serverScanExecutor).get(); @@ -914,16 +905,6 @@ public class InventoryManager extends AgentService implements ContainerService, return true; }
- //finish the resource upgrade. - //by now all the resource upgrade requests have been processed - //by the executor, which means that the inventory report - //we got already only contains the "correct" new resources and - //that the executor has all the upgrade requests queued up - //to be sent to the server in a batch. - if (resourceUpgradeExecutor.isEnabled()) { - resourceUpgradeExecutor.sendRequests(); - } - if (report.getAddedRoots().isEmpty() && !forceServerRoundtrip) { return true; // nothing to do } @@ -1005,7 +986,12 @@ public class InventoryManager extends AgentService implements ContainerService, // so run an avail check to report on their availabilities immediately. Also kick off // a service scan to scan those Resources for new child Resources. Kick both tasks off // asynchronously. - if (!syncedResources.isEmpty() || !unknownResourceIds.isEmpty() || !modifiedResourceIds.isEmpty()) { + // Do this only if we are finished with resource upgrade because no availability checks + // or discoveries can happen during upgrade. This is to ensure maximum consistency of the + // inventory with the server side as well as to disallow any other server-agent traffic during + // the upgrade phase. Not to mention the fact that no thread pools are initialized yet by the + // time the upgrade kicks in.. + if (!resourceUpgradeDelegate.enabled() && (!syncedResources.isEmpty() || !unknownResourceIds.isEmpty() || !modifiedResourceIds.isEmpty())) { performAvailabilityChecks(true); this.inventoryThreadPoolExecutor.schedule((Callable<? extends Object>) this.serviceScanExecutor, 5, TimeUnit.SECONDS); @@ -2180,10 +2166,6 @@ public class InventoryManager extends AgentService implements ContainerService, newResources.add(newResource); } } - - if (resourceUpgradeExecutor.isEnabled()) { - resourceUpgradeExecutor.processAndQueue(new ResourceUpgradePendingRequest(newResources, context, parentResource.getId()), newResources); - } } catch (Throwable e) { // TODO GH: Add server/parent - up/down semantics so this won't happen just because a server is not up long elapsedTime = System.currentTimeMillis() - startTime; @@ -2594,6 +2576,63 @@ public class InventoryManager extends AgentService implements ContainerService, container.setSynchronizationState(ResourceContainer.SynchronizationState.SYNCHRONIZED); }
+ private void upgradeResources() { + try { + if (log.isDebugEnabled()) { + log.debug("Executing resource upgrade."); + } + + boolean syncResult = handleReport(new InventoryReport(getAgent()), true); + if (!syncResult) { + log.warn("Resource upgrade failed to sync up the inventory with the server."); + return; + } + + upgradeResource(getPlatform()); + + if (log.isDebugEnabled()) { + log.debug("Sending the upgrade requests to the server."); + } + resourceUpgradeDelegate.sendRequests(); + + resourceUpgradeDelegate.disable(); + + if (log.isDebugEnabled()) { + log.debug("Resource upgrade finished."); + } + } catch (Throwable t) { + log.error("Resource upgrade failed with an exception.", t); + } + } + + private void upgradeResource(Resource resource) { + //only process committed resources + if (resource.getInventoryStatus() != InventoryStatus.COMMITTED) { + return; + } + + ResourceContainer container = getResourceContainer(resource); + if (container != null) { + try { + container = getResourceContainer(resource); + resourceUpgradeDelegate.processAndQueue(container); + } catch (PluginContainerException e) { + log.error("Exception thrown while upgrading [" + resource + "]."); + } + + if (container.getResourceComponentState() == ResourceComponentState.STARTED) { + for (Resource child : resource.getChildResources()) { + upgradeResource(child); + } + } else { + log.error("The resource container for resource [" + resource + "] wasn't started during upgrade. This should not happen."); + } + } else { + log.error("Resource container not initialized for resource [" + resource + + "] during upgrade. This should not happen."); + } + } + /** * That class implements a listener that gets called when the resource got activated * @author hrupp diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java new file mode 100644 index 0000000..cb466bd --- /dev/null +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeDelegate.java @@ -0,0 +1,180 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.core.pc.upgrade; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.rhq.core.clientapi.agent.PluginContainerException; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceUpgradeReport; +import org.rhq.core.pc.PluginContainer; +import org.rhq.core.pc.inventory.InventoryManager; +import org.rhq.core.pc.inventory.ResourceContainer; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; + +/** + * This is a helper class to {@link InventoryManager} that takes care of resource upgrade. + * Note that this class is not thread-safe in any manner. + * + * @author Lukas Krejci + */ +public class ResourceUpgradeDelegate { + + private static final Log log = LogFactory.getLog(ResourceUpgradeDelegate.class); + + private boolean enabled = true; + + private Set<ResourceUpgradeRequest> requests = new HashSet<ResourceUpgradeRequest>(); + private InventoryManager inventoryManager; + + public ResourceUpgradeDelegate(InventoryManager inventoryManager) { + this.inventoryManager = inventoryManager; + } + + /** + * Is the delegate enabled? In another words has the resource upgrade phase finished in the {@link IventoryManager#initialize()} + * method? + */ + public boolean enabled() { + return enabled; + } + + /** + * Disables all future operations of the delegate. + */ + public void disable() { + enabled = false; + } + + /** + * Asks the resource's discovery component to upgrade the resource. + * @param resourceContainer + * @return true if the resource was queued for upgrade, false otherwise + * @throws PluginContainerException on error + */ + public boolean processAndQueue(ResourceContainer resourceContainer) throws PluginContainerException { + if (enabled) { + return executeResourceUpgradeFacetAndStoreRequest(resourceContainer); + } + + return false; + } + + public void sendRequests() { + if (enabled) { + if (requests.size() > 0) { + inventoryManager.mergeResourceFromUpgrade(requests); + requests.clear(); + } + } + } + + private <T extends ResourceComponent> boolean executeResourceUpgradeFacetAndStoreRequest( + ResourceContainer resourceContainer) throws PluginContainerException { + + @SuppressWarnings("unchecked") + ResourceComponent<T> parentResourceComponent = resourceContainer.getResourceContext() + .getParentResourceComponent(); + + Resource parentResource = resourceContainer.getResource().getParentResource(); + + ResourceContainer parentResourceContainer = (parentResource != null) ? inventoryManager + .getResourceContainer(resourceContainer.getResource().getParentResource()) : null; + + Resource resource = resourceContainer.getResource(); + + @SuppressWarnings("unchecked") + ResourceDiscoveryComponent<ResourceComponent<T>> discoveryComponent = PluginContainer.getInstance() + .getPluginComponentFactory().getDiscoveryComponent(resource.getResourceType(), parentResourceContainer); + + if (!(discoveryComponent instanceof ResourceUpgradeFacet)) { + //well, there's no point in continuing if the resource doesn't support the facet + return false; + } + + ResourceUpgradeContext<ResourceComponent<T>> upgradeContext = inventoryManager.createResourceUpgradeContext( + resource, parentResourceComponent, discoveryComponent); + + ResourceUpgradeReport upgradeReport; + try { + upgradeReport = inventoryManager.invokeDiscoveryComponentResourceUpgradeFacet(resource.getResourceType(), + discoveryComponent, upgradeContext); + } catch (Throwable t) { + log.error("ResourceUpgradeFacet threw an exception while upgrading resource [" + resource + "]", t); + return false; + } + + if (upgradeReport == null || !upgradeReport.hasSomethingToUpgrade()) { + return false; + } + + String upgradeErrors = null; + if ((upgradeErrors = checkUpgradeValid(resource, upgradeReport)) != null) { + log.error("Upgrading the resource [" + resource + "] using these updates [" + upgradeReport + + "] would render the inventory invalid because of the following reasons: " + upgradeErrors); + return false; + } + + //everything went ok, let's queue a upgrade request that will be sent to the server + requests.add(new ResourceUpgradeRequest(resource.getId(), upgradeReport)); + + return true; + } + + private String checkUpgradeValid(Resource resource, ResourceUpgradeReport upgradeReport) { + StringBuilder bld = new StringBuilder(); + + if (!checkResourceKeyUniqueAmongSiblings(resource, upgradeReport)) { + bld.append("\nAnother inventoried sibling resource of the same type already has the proposed resource key."); + } + + return bld.length() > 0 ? bld.toString() : null; + } + + private boolean checkResourceKeyUniqueAmongSiblings(Resource resource, ResourceUpgradeReport upgradeReport) { + Resource parent = resource.getParentResource(); + if (parent == null) { + return true; + } + + for (Resource sibling : parent.getChildResources()) { + //we'd have a resource key conflict if there was a resource + //of the same type under the same parent that would have the same + //resource key. + if (upgradeReport.getNewResourceKey() != null + && sibling.getResourceType().equals(resource.getResourceType()) + && !sibling.getUuid().equals(resource.getUuid())) { + + if (sibling.getResourceKey().equals(upgradeReport.getNewResourceKey())) { + return false; + } + } + } + + return true; + } +} diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java deleted file mode 100644 index f344900..0000000 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2010 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, version 2, as - * published by the Free Software Foundation, and/or the GNU Lesser - * General Public License, version 2.1, also as published by the Free - * Software Foundation. - * - * 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 and the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * and the GNU Lesser 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.core.pc.upgrade; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.rhq.core.clientapi.agent.PluginContainerException; -import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; -import org.rhq.core.clientapi.server.discovery.InventoryReport; -import org.rhq.core.domain.resource.InventoryStatus; -import org.rhq.core.domain.resource.Resource; -import org.rhq.core.domain.resource.ResourceType; -import org.rhq.core.domain.resource.ResourceUpgradeReport; -import org.rhq.core.pc.PluginContainer; -import org.rhq.core.pc.inventory.InventoryManager; -import org.rhq.core.pc.inventory.ResourceContainer; -import org.rhq.core.pluginapi.inventory.ResourceComponent; -import org.rhq.core.pluginapi.inventory.ResourceContext; -import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; -import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; -import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; -import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; - -/** - * This class is responsible for performing the resource upgrade on behalf on of {@link InventoryManager}. - * Despite its name, it is not an {@link java.util.concurrent.Executor} implementation. - * - * @author Lukas Krejci - */ -public class ResourceUpgradeExecutor implements Runnable { - private static final Log log = LogFactory.getLog(ResourceUpgradeExecutor.class); - - /** - * The upgrade runs only once in its lifetime. - */ - private AtomicBoolean enabled = new AtomicBoolean(true); - private AtomicBoolean started = new AtomicBoolean(false); - - private InventoryManager inventoryManager; - - private ConcurrentLinkedQueue<ResourceUpgradeRequest> requests; - - public ResourceUpgradeExecutor(InventoryManager inventoryManager) { - this.inventoryManager = inventoryManager; - requests = new ConcurrentLinkedQueue<ResourceUpgradeRequest>(); - } - - /** - * This method is called from within the {@link InventoryManager} during the - * discovery process as individual upgrade requests are generated. - * <p> - * This method calls the appropriate discovery component to perform the upgrade and - * at the same time stores off the results so that they can be sent to the server - * at the end of the discovery in one big batch. - * <p> - * The provided set of discovery results is updated if this method detects that an existing - * resource upgrade would result in a resource key collision with some of the newly discovered - * resources. - * - * @param request the upgrade request - * @param discoveredResources the set of discovered resources that this method can optionally remove some elements from. - */ - public <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> processAndQueue( - ResourceUpgradePendingRequest<T> request, Set<Resource> discoveredResources) { - - return enabled.get() ? executeResourceUpgradeAndStoreRequest(request, discoveredResources) : null; - } - - /** - * @return true if the executor is ready to perform the upgrade, false otherwise. - */ - public boolean isEnabled() { - return enabled.get(); - } - - /** - * This method is called from within the {@link InventoryManager} once it's collected - * all the upgrade requests. - */ - public void sendRequests() { - if (enabled.get() && requests.size() > 0) { - HashSet<ResourceUpgradeRequest> currentCopy = new HashSet<ResourceUpgradeRequest>(requests); - inventoryManager.mergeResourceFromUpgrade(currentCopy); - requests.removeAll(currentCopy); - } - } - - /** - * Performs the resource upgrade. First, a full inventory report is pulled down from the - * server to ensure we have an up-to-date picture of the inventory. - * After that a full discovery is performed and both the upgrade report and discovery report - * are sent to the server. - */ - public void run() { - if (!started.getAndSet(true)) { - if (log.isDebugEnabled()) { - log.debug("Starting resource upgrade."); - } - - try { - //pull the inventory down from the server. - //this will ensure that we have an up-to-date info on the - //server inventory before we try to upgrade. - boolean syncResult = inventoryManager.handleReport(new InventoryReport(inventoryManager.getAgent()), true); - if (!syncResult) { - log.warn("Resource upgrade failed to sync up the inventory with the server."); - return; - } - - //fire off the full discovery - inventoryManager.executeServerScanImmediately(); - inventoryManager.executeServiceScanImmediately(); - } catch (Throwable t) { - log.warn("Resource upgrade failed.", t); - } finally { - //make sure to switch off the upgrade... - this.enabled.set(false); - - //clear up so that we don't hold unnecessary instances. - requests.clear(); - - if (log.isDebugEnabled()) { - log.debug("Resource upgrade finished."); - } - } - - } else { - if (log.isDebugEnabled()) { - log.debug("ResourceUpgradeExecutor already ran before. Skipping the execution."); - } - } - } - - /** - * Executes the resource upgrade request on the agent (if the appropriate discovery component support {@link ResourceUpgradeFacet}). - * - * @param request the upgrade request to execute on the agent. - * @param discoveredResources the set of the discovered resources that this method can remove some elements from - * @return the resulting upgrade map as reported by the plugin from {@link ResourceUpgradeFacet#upgrade(Set, ResourceUpgradeContext, Set)} method. - * - * @throws PluginContainerException - */ - private <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> executeResourceUpgradeAndStoreRequest( - ResourceUpgradePendingRequest<T> request, Set<Resource> discoveredResources) { - - ResourceDiscoveryContext<T> discoveryContext = request.getDiscoveryContext(); - Set<Resource> newResources = request.getDiscoveredResources(); - Integer parentResourceId = request.getParentResourceId(); - - try { - ResourceType resourceType = discoveryContext.getResourceType(); - ResourceContainer parentResourceContainer = null; - Resource parentResource = null; - if (parentResourceId != null) { - parentResourceContainer = inventoryManager.getResourceContainer(parentResourceId); - if (parentResourceContainer != null) { - parentResource = parentResourceContainer.getResource(); - } - } - - @SuppressWarnings("unchecked") - ResourceDiscoveryComponent<T> discoveryComponent = PluginContainer.getInstance() - .getPluginComponentFactory().getDiscoveryComponent(resourceType, parentResourceContainer); - - ResourceContext<?> parentResourceContext = discoveryContext.getParentResourceContext(); - - T parentComponent = discoveryContext.getParentResourceComponent(); - - //check if the discovery component supports resource upgrade - //if it does, perform the resource upgrade straight away here during the discovery process. - if (discoveryComponent instanceof ResourceUpgradeFacet) { - //the siblings are the resources of the type that is currently being discovered that are already - //present in the inventory. These are the candidate resources for the upgrade. - Set<Resource> siblings = parentResource == null ? Collections.singleton(inventoryManager.getPlatform()) - : inventoryManager.getResourcesWithType(resourceType, parentResource.getChildResources()); - - //filter out not committed resources - //XXX what about uninventoried or ignored ones? is it correct to not upgrade those? - Iterator<Resource> siblingsIterator = siblings.iterator(); - while (siblingsIterator.hasNext()) { - if (siblingsIterator.next().getInventoryStatus() != InventoryStatus.COMMITTED) { - siblingsIterator.remove(); - } - } - - //get the upgrade context of the parent resource so that it can be passed to the upgrade method - //of the discovery component. - ResourceUpgradeContext<?> parentUpgradeContext = null; - - if (parentResource != null) { - Resource grandParent = parentResource.getParentResource(); - ResourceContainer grandParentContainer = grandParent == null ? null : inventoryManager - .getResourceContainer(grandParent); - - @SuppressWarnings("unchecked") - ResourceDiscoveryComponent<ResourceComponent> parentDiscoveryComponent = PluginContainer - .getInstance().getPluginComponentFactory().getDiscoveryComponent( - parentResource.getResourceType(), grandParentContainer); - - ResourceComponent<?> grandParentResourceComponent = grandParentContainer == null ? null - : grandParentContainer.getResourceComponent(); - - parentUpgradeContext = inventoryManager.createResourceUpgradeContext(parentResource, - grandParentResourceComponent, parentDiscoveryComponent); - } - - //convert the sibling resources into upgrade context objects so that the plugin methods don't access the - //domain objects directly. - Set<ResourceUpgradeContext<T>> siblingContexts = new HashSet<ResourceUpgradeContext<T>>(siblings.size()); - - //but we are going to need to update the resources in the end, so map the contexts with the resources. - Map<ResourceUpgradeContext<T>, Resource> siblingContextToResource = new HashMap<ResourceUpgradeContext<T>, Resource>(); - - for (Resource sibling : siblings) { - ResourceUpgradeContext<T> siblingContext = inventoryManager.createResourceUpgradeContext(sibling, - parentComponent, discoveryComponent); - siblingContexts.add(siblingContext); - siblingContextToResource.put(siblingContext, sibling); - } - - //convert the new resources into contexts. - //map the resources by resource key so that we can later check for uniqueness of the reported results. - Set<ResourceUpgradeContext<T>> newResourceContexts = new HashSet<ResourceUpgradeContext<T>>(); - Map<String, Resource> newResourceKeyToResource = new HashMap<String, Resource>(); - - for (Resource newResource : newResources) { - ResourceUpgradeContext<T> newUpgradeContext = inventoryManager.createResourceUpgradeContext( - newResource, parentComponent, discoveryComponent); - newResourceContexts.add(newUpgradeContext); - newResourceKeyToResource.put(newResource.getResourceKey(), newResource); - } - - //ask the discovery component to upgrade the siblings. - Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> results; - try { - results = inventoryManager.invokeDiscoveryComponentResourceUpgradeFacet(resourceType, - discoveryComponent, siblingContexts, parentUpgradeContext, newResourceContexts); - - //now go through the results and create the upgrade requests. - for (Map.Entry<ResourceUpgradeContext<T>, ResourceUpgradeReport> upgradeEntry : results.entrySet()) { - Resource siblingToUpgrade = siblingContextToResource.get(upgradeEntry.getKey()); - ResourceUpgradeRequest newData = new ResourceUpgradeRequest(siblingToUpgrade.getId(), upgradeEntry.getValue()); - - requests.add(newData); - - //if there was a resource key upgrade, remove a resource with the same resource key - //from the discovery results. Otherwise we'd end up with 2 sibling resources with - //the same resource key, which is illegal. - if (newData.getNewResourceKey() != null) { - Resource newResourceToRemove = newResourceKeyToResource.get(newData.getNewResourceKey()); - if (newResourceToRemove != null) { - discoveredResources.remove(newResourceToRemove); - } - } - } - - return results; - } catch (Throwable t) { - log.warn("Exception in discovery component " + discoveryComponent.getClass() + " upgrade method.", - t); - } - } - } catch (PluginContainerException e) { - log.warn("Failed resource upgrade of children of resource id " + parentResourceId, e); - } - return null; - } -} diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradePendingRequest.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradePendingRequest.java deleted file mode 100644 index 1099643..0000000 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradePendingRequest.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.rhq.core.pc.upgrade; - -import java.util.Set; - -import org.rhq.core.domain.resource.Resource; -import org.rhq.core.pluginapi.inventory.ResourceComponent; -import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; - -/** - * This class is used to store the requests for resource upgrade that originate in - * the discovery workflow, but can only be executed after an inventory sync. - */ -public class ResourceUpgradePendingRequest<T extends ResourceComponent> { - private Set<Resource> discoveredResources; - private ResourceDiscoveryContext<T> discoveryContext; - private Integer parentResourceId; - - public ResourceUpgradePendingRequest(Set<Resource> discoveredResources, ResourceDiscoveryContext<T> discoveryContext, Integer parentResourceId) { - this.discoveredResources = discoveredResources; - this.discoveryContext = discoveryContext; - this.parentResourceId = parentResourceId; - } - - public Set<Resource> getDiscoveredResources() { - return discoveredResources; - } - - public ResourceDiscoveryContext<T> getDiscoveryContext() { - return discoveryContext; - } - - public Integer getParentResourceId() { - return parentResourceId; - } -} \ No newline at end of file diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index 087b46f..b5d571f 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -151,34 +151,8 @@ public class ResourceUpgradeTest { }
@Test - public void testResourceUpgradeRunsOnlyOnce() throws Exception { - currentServerSideInventory = new FakeServerInventory(); - initialSyncAndDiscovery(InventoryStatus.COMMITTED); - - executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, new TestPayload() { - public void test(Resource discoveredResource) { - for(int i = 0; i < 100; i++) { - PluginContainer.getInstance().getInventoryManager().fireResourceUpgrade(); - } - } - - @SuppressWarnings("unchecked") - public Expectations getExpectations(Mockery context) throws Exception { - return new Expectations() { - { - defineDefaultExpectations(this); - - between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); - will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); - - //even though we fire the resource upgrade 100 times above, - //only 1 upgrade should actually occur and go up to the server. - oneOf(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); - will(currentServerSideInventory.upgradeResources()); - } - }; - } - }); + public void testRecoveryWithServerUnavailable() throws Exception { + //TODO implement }
private void initialSyncAndDiscovery(final InventoryStatus requiredInventoryStatus) throws Exception { diff --git a/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar b/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar index 412ae00..7ffc5bb 100644 Binary files a/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar and b/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar differ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index 329f476..add8168 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -20,7 +20,6 @@ package org.rhq.enterprise.server.discovery;
import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java index 7fe7a5e..de265eb 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java @@ -1715,8 +1715,16 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage Query query = entityManager.createNamedQuery(Resource.QUERY_FIND_PLATFORM_BY_AGENT); query.setParameter("category", ResourceCategory.PLATFORM); query.setParameter("agent", agent); - Resource platform = (Resource) query.getSingleResult(); - return platform; + + try { + Resource platform = (Resource) query.getSingleResult(); + return platform; + } catch (NoResultException e) { + //this means that the agent didn't send any info to us yet. + //this can happen during the inital resource upgrade sync between + //the agent and server. + return null; + } }
@SuppressWarnings("unchecked") diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java index 327c439..faf0b11 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java @@ -376,7 +376,7 @@ public interface ResourceManagerLocal { * * @param agent an Agent * - * @return the platform Resource associated with the specified Agent + * @return the platform Resource associated with the specified Agent or null if the platform for the agent is not known yet. */ Resource getPlatform(Agent agent);
diff --git a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java index 362a1df..c31d153 100644 --- a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java +++ b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java @@ -170,45 +170,40 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen return discoveredResources; }
- public Map<ResourceUpgradeContext<PlatformComponent>, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext<PlatformComponent>> inventoriedSiblings, - ResourceUpgradeContext<?> parentContext, Set<ResourceUpgradeContext<PlatformComponent>> discoveryResults) { - - Map<ResourceUpgradeContext<PlatformComponent>, ResourceUpgradeReport> ret = new HashMap<ResourceUpgradeContext<PlatformComponent>, ResourceUpgradeReport>(); - - for (ResourceUpgradeContext context : inventoriedSiblings) { - String inventoriedResourceKey = context.getResourceKey(); - File inventoriedResourceKeyAsPath = new File(inventoriedResourceKey); - - //the resource key we use now is a full path to the httpdconf. - //in the old version, it was the server root. - //so if the inventoried resource key is a path to a file, - //we know it's a new style resource key. - if (inventoriedResourceKeyAsPath.isFile()) { - continue; - } - - Configuration pluginConfiguration = context.getPluginConfiguration(); - - String serverRoot = pluginConfiguration.getSimpleValue("serverRoot", null); - String httpdConf = pluginConfiguration.getSimpleValue("configFile", null); - - String resourceKey = null; - - if (httpdConf != null) { - File httpdConfFile = new File(httpdConf); - if (!httpdConfFile.isAbsolute()) { - httpdConfFile = new File(serverRoot, httpdConf); - } - - resourceKey = httpdConfFile.getPath(); - - ResourceUpgradeReport rep = new ResourceUpgradeReport(); - rep.setNewResourceKey(resourceKey); - - ret.put(context, rep); + public ResourceUpgradeReport upgrade(ResourceUpgradeContext<PlatformComponent> context) { + String inventoriedResourceKey = context.getResourceKey(); + File inventoriedResourceKeyAsPath = new File(inventoriedResourceKey); + + //the resource key we use now is a full path to the httpd.conf. + //in the old version, it was the server root. + //so if the inventoried resource key is a path to a file, + //we know it's a new style resource key. + if (inventoriedResourceKeyAsPath.isFile()) { + return null; + } + + Configuration pluginConfiguration = context.getPluginConfiguration(); + + String serverRoot = pluginConfiguration.getSimpleValue("serverRoot", null); + String httpdConf = pluginConfiguration.getSimpleValue("configFile", null); + + String resourceKey = null; + + if (httpdConf != null) { + File httpdConfFile = new File(httpdConf); + if (!httpdConfFile.isAbsolute()) { + httpdConfFile = new File(serverRoot, httpdConf); } + + resourceKey = httpdConfFile.getPath(); + + ResourceUpgradeReport rep = new ResourceUpgradeReport(); + rep.setNewResourceKey(resourceKey); + + return rep; } - return ret; + + return null; }
public DiscoveredResourceDetails discoverResource(Configuration pluginConfig,
commit 00b2aae2f27dd64092eee3c2d09df33e48736e10 Merge: 90ca72b... ed06919... Author: Lukas Krejci lkrejci@redhat.com Date: Fri Jul 2 14:25:47 2010 +0200
Merge branch 'release-3.0.0' into resource-upgrade
diff --cc modules/core/dbutils/pom.xml index 2013b3d,d536ce6..96685db --- a/modules/core/dbutils/pom.xml +++ b/modules/core/dbutils/pom.xml @@@ -22,7 -22,7 +22,7 @@@
<properties> <scm.module.path>modules/core/dbutils/</scm.module.path> -- <db.schema.version>2.88</db.schema.version> ++ <db.schema.version>2.89</db.schema.version> </properties>
<dependencies> diff --cc modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index 3ee8217,7f8f9da..20e9d2f --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@@ -2994,15 -3000,17 +3000,27 @@@ </statement> </schema-directSQL> </schemaSpec> - - <schemaSpec version="2.88"> + + <schemaSpec version="2.88"> + <schema-directSQL> + <statement desc="Add end time index on call time data to speed up purges"> + CREATE INDEX RHQ_CT_DA_VA_END_TIM_IDX ON RHQ_CALLTIME_DATA_VALUE (end_time) + </statement> + <statement desc="Add index on measurement definition numeric type"> + CREATE INDEX RHQ_METRIC_DEF_NT_IDX ON RHQ_MEASUREMENT_DEF (numeric_type) + </statement> + </schema-directSQL> + </schemaSpec> ++ ++ <schemaSpec version="2.89"> + <schema-directSQL> + <statement desc="Adding 'Allow Agent Plugins To Upgrade Generic Resource Properties' system configuration setting"> + INSERT INTO rhq_system_config (id, property_key, property_value, default_property_value) + VALUES (56, 'RESOURCE_GENERIC_PROPERTIES_UPGRADE', 'false', 'false') + </statement> + </schema-directSQL> + </schemaSpec> ++ </dbupgrade> </target> </project>
commit 90ca72b3aa73f41165ab2d616f53f12d642bef7d Merge: 5449040... b9ca90d... Author: Lukas Krejci lkrejci@redhat.com Date: Wed Jun 23 19:01:34 2010 +0200
Merge branch 'release-3.0.0' into resource-upgrade
commit 54490406d19753524b052beeab418af68bf68c2c Author: Lukas Krejci lkrejci@redhat.com Date: Wed Jun 23 15:41:36 2010 +0200
Restructuring the tests a bit, adding a test for correct reinitialization of the agent inventory from the server inventory during the resource upgrade.
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java index 46d069c..087b46f 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -49,6 +49,7 @@ import org.rhq.core.clientapi.server.event.EventServerService; import org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService; import org.rhq.core.clientapi.server.measurement.MeasurementServerService; import org.rhq.core.clientapi.server.operation.OperationServerService; +import org.rhq.core.domain.discovery.AvailabilityReport; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; @@ -64,6 +65,7 @@ import org.rhq.core.pc.plugin.FileSystemPluginFinder; * * @author Lukas Krejci */ +@Test(sequential = true, invocationCount = 1) public class ResourceUpgradeTest {
private static final String PLUGIN_V1_FILENAME = "resource-upgrade-test-plugin-1.0.0.jar"; @@ -100,7 +102,7 @@ public class ResourceUpgradeTest { verifyPluginExists(PLUGIN_V2_FILENAME); }
- @BeforeClass + @BeforeClass(dependsOnMethods = "sanityCheck") public void init() { tmpDir = getTmpDirectory(); pluginDir = new File(tmpDir, PLUGINS_DIR_NAME); @@ -110,12 +112,10 @@ public class ResourceUpgradeTest { }
@Test - public void testInitialSyncAndDiscoveryWithoutCommit() throws Exception { - testInitialSyncAndDiscovery(InventoryStatus.NEW); - } - - @Test(dependsOnMethods = "testInitialSyncAndDiscoveryWithoutCommit") public void testIgnoreUncommittedResources() throws Exception { + currentServerSideInventory = new FakeServerInventory(); + initialSyncAndDiscovery(InventoryStatus.NEW); + TestPayload testNoChange = new TestPayload() { public void test(Resource discoveredResource) { assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); @@ -123,17 +123,13 @@ public class ResourceUpgradeTest { assertEquals(discoveredResource.getDescription(), "resource-description-v1"); }
- @SuppressWarnings("unchecked") public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { - defineIgnoredExpectations(this); + defineDefaultExpectations(this);
between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); - - allowing(currentDiscoveryServerService).getResources(with(any(Set.class)), with(any(boolean.class))); - will(currentServerSideInventory.getResources()); } }; } @@ -142,52 +138,50 @@ public class ResourceUpgradeTest { executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, testNoChange); }
- //make the tests run serially, so that they don't overwrite the currentServerSideInventory - //variable concurrently - @Test(dependsOnMethods = "testIgnoreUncommittedResources") - public void testInitialSyncAndDiscoveryWithCommit() throws Exception { - testInitialSyncAndDiscovery(InventoryStatus.COMMITTED); - } - - @Test(dependsOnMethods = "testInitialSyncAndDiscoveryWithCommit") + @Test public void testUpgradeData() throws Exception { - //we are keeping the currentServerSideInventory from the previous test + currentServerSideInventory = new FakeServerInventory(); + upgradeTest(false); + } + + @Test + public void testInventoryReinitializationFromServerDuringUpgrade() throws Exception { + currentServerSideInventory = new FakeServerInventory(); + upgradeTest(true); + } + + @Test + public void testResourceUpgradeRunsOnlyOnce() throws Exception { + currentServerSideInventory = new FakeServerInventory(); + initialSyncAndDiscovery(InventoryStatus.COMMITTED); + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, new TestPayload() { public void test(Resource discoveredResource) { - assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); - assertEquals(discoveredResource.getName(), "resource-name-v2"); - assertEquals(discoveredResource.getDescription(), "resource-description-v2"); - - ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(discoveredResource); - File dataDir = container.getResourceContext().getDataDirectory(); - - File marker = new File(dataDir, "upgrade-succeeded"); - - assertTrue(marker.exists(), "The upgrade success marker file wasn't found. This means the upgrade didn't actually run."); + for(int i = 0; i < 100; i++) { + PluginContainer.getInstance().getInventoryManager().fireResourceUpgrade(); + } }
@SuppressWarnings("unchecked") public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { - defineIgnoredExpectations(this); + defineDefaultExpectations(this);
between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED));
+ //even though we fire the resource upgrade 100 times above, + //only 1 upgrade should actually occur and go up to the server. oneOf(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); will(currentServerSideInventory.upgradeResources()); - - allowing(currentDiscoveryServerService).getResources(with(any(Set.class)), with(any(boolean.class))); - will(currentServerSideInventory.getResources()); } }; } }); }
- private void testInitialSyncAndDiscovery(final InventoryStatus requiredInventoryStatus) throws Exception { - currentServerSideInventory = new FakeServerInventory(); + private void initialSyncAndDiscovery(final InventoryStatus requiredInventoryStatus) throws Exception { executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), true, new TestPayload() { public void test(Resource discoveredResource) { assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); @@ -195,17 +189,13 @@ public class ResourceUpgradeTest { assertEquals(discoveredResource.getDescription(), "resource-description-v1"); }
- @SuppressWarnings("unchecked") public Expectations getExpectations(Mockery context) throws Exception { return new Expectations() { { - defineIgnoredExpectations(this); + defineDefaultExpectations(this);
between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); will(currentServerSideInventory.mergeInventoryReport(requiredInventoryStatus)); - - allowing(currentDiscoveryServerService).getResources(with(any(Set.class)), with(any(boolean.class))); - will(currentServerSideInventory.getResources()); } }; } @@ -213,6 +203,40 @@ public class ResourceUpgradeTest {
}
+ private void upgradeTest(boolean clearInventoryDat) throws Exception { + initialSyncAndDiscovery(InventoryStatus.COMMITTED); + + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), clearInventoryDat, new TestPayload() { + public void test(Resource discoveredResource) { + assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); + assertEquals(discoveredResource.getName(), "resource-name-v2"); + assertEquals(discoveredResource.getDescription(), "resource-description-v2"); + + ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(discoveredResource); + File dataDir = container.getResourceContext().getDataDirectory(); + + File marker = new File(dataDir, "upgrade-succeeded"); + + assertTrue(marker.exists(), "The upgrade success marker file wasn't found. This means the upgrade didn't actually run."); + } + + @SuppressWarnings("unchecked") + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineDefaultExpectations(this); + + between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); + will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + + oneOf(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); + will(currentServerSideInventory.upgradeResources()); + } + }; + } + }); + } + private PluginContainerConfiguration createPluginContainerConfiguration(Mockery context) throws Exception { PluginContainerConfiguration conf = new PluginContainerConfiguration();
@@ -223,6 +247,15 @@ public class ResourceUpgradeTest { conf.setPluginFinder(new FileSystemPluginFinder(conf.getPluginDirectory())); conf.setCreateResourceClassloaders(false);
+ //we're not interested in any scans happening out of our control + conf.setAvailabilityScanInitialDelay(Long.MAX_VALUE); + conf.setConfigurationDiscoveryInitialDelay(Long.MAX_VALUE); + conf.setContentDiscoveryInitialDelay(Long.MAX_VALUE); + conf.setEventSenderInitialDelay(Long.MAX_VALUE); + conf.setMeasurementCollectionInitialDelay(Long.MAX_VALUE); + conf.setServerDiscoveryInitialDelay(Long.MAX_VALUE); + conf.setServiceDiscoveryInitialDelay(Long.MAX_VALUE); + currentBundleServerService = context.mock(BundleServerService.class); currentConfigurationServerService = context.mock(ConfigurationServerService.class); currentContentServerService = context.mock(ContentServerService.class); @@ -332,7 +365,8 @@ public class ResourceUpgradeTest { context.assertIsSatisfied(); }
- private void defineIgnoredExpectations(Expectations expectations) { + @SuppressWarnings("unchecked") + private void defineDefaultExpectations(Expectations expectations) { expectations.ignoring(currentBundleServerService); expectations.ignoring(currentConfigurationServerService); expectations.ignoring(currentContentServerService); @@ -341,5 +375,11 @@ public class ResourceUpgradeTest { expectations.ignoring(currentMeasurementServerService); expectations.ignoring(currentOperationServerService); expectations.ignoring(currentResourceFactoryServerService); + + //just ignore these invocations if we get a availability scan in the PC... + expectations.allowing(currentDiscoveryServerService).mergeAvailabilityReport(expectations.with(Expectations.any(AvailabilityReport.class))); + + expectations.allowing(currentDiscoveryServerService).getResources(expectations.with(Expectations.any(Set.class)), expectations.with(Expectations.any(boolean.class))); + expectations.will(currentServerSideInventory.getResources()); } }
commit 0d5d63e1ed0825ddc0ea256b695a66c980b69e6e Author: Lukas Krejci lkrejci@redhat.com Date: Wed Jun 23 15:40:16 2010 +0200
Forgot to bump the db version.
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml index 92ae1d2..2013b3d 100644 --- a/modules/core/dbutils/pom.xml +++ b/modules/core/dbutils/pom.xml @@ -22,7 +22,7 @@
<properties> <scm.module.path>modules/core/dbutils/</scm.module.path> - <db.schema.version>2.87</db.schema.version> + <db.schema.version>2.88</db.schema.version> </properties>
<dependencies>
commit 7f8310f4d3648ba3386fda883563bdcc8c5d1492 Author: Lukas Krejci lkrejci@redhat.com Date: Wed Jun 23 15:39:54 2010 +0200
Adding the server side system config property for controlling whether to allow resource name and description upgrades.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/config/SystemConfigForm.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/config/SystemConfigForm.java index 237858d..508a4ac 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/config/SystemConfigForm.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/config/SystemConfigForm.java @@ -66,7 +66,8 @@ public class SystemConfigForm extends BaseValidatorForm { private String ldapPassword = ""; private Boolean ldapEnabled = null; private boolean reindex = false; - + private boolean allowResourceGenericPropertiesUpgrade; + @Override public String toString() { StringBuffer buf = new StringBuffer(super.toString()); @@ -230,6 +231,8 @@ public class SystemConfigForm extends BaseValidatorForm { String jaasProvider = prop.getProperty(RHQConstants.JAASProvider); ldapEnabled = RHQConstants.LDAPJAASProvider.equals(jaasProvider) ? Boolean.TRUE : null;
+ String resourceGenericPropertiesUpgradeAllowed = prop.getProperty(RHQConstants.AllowResourceGenericPropertiesUpgrade); + allowResourceGenericPropertiesUpgrade = Boolean.parseBoolean(resourceGenericPropertiesUpgradeAllowed); }
/** @@ -332,6 +335,8 @@ public class SystemConfigForm extends BaseValidatorForm { prop.setProperty(RHQConstants.JAASProvider, RHQConstants.JDBCJAASProvider); }
+ prop.setProperty(RHQConstants.AllowResourceGenericPropertiesUpgrade, String.valueOf(allowResourceGenericPropertiesUpgrade)); + return prop; }
@@ -608,6 +613,14 @@ public class SystemConfigForm extends BaseValidatorForm { public void setReindex(boolean reindex) { this.reindex = reindex; } + + public boolean isAllowResourceGenericPropertiesUpgrade() { + return allowResourceGenericPropertiesUpgrade; + } + + public void setAllowResourceGenericPropertiesUpgrade(boolean allowResourceGenericPropertiesUpgrade) { + this.allowResourceGenericPropertiesUpgrade = allowResourceGenericPropertiesUpgrade; + }
/* (non-Javadoc) * @see org.apache.struts.action.ActionForm#validate(org.apache.struts.action.ActionMapping, diff --git a/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties b/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties index f02efb5..83f42f0 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties +++ b/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties @@ -667,6 +667,8 @@ admin.settings.ServerPluginsConfigPropTab=Server Plugins Configuration Propertie admin.settings.UseCAMAuth=Use ${product.shortName} Internal Authentication admin.settings.UseLDAPAuth=Use LDAP Authentication
+admin.settings.AllowResourceGenericPropertiesUpgrade=Allow Agent Plugins To Upgrade Generic Resource Properties + admin.settings.error.DeleteUnitsField=Value must be between 1 and 7 days. admin.settings.error.InvalidSNMPTrapOID=SNMP Trap OID invalid, please enter OID in form of 1.2.3.4. admin.settings.error.InvalidSNMPEngineID=SNMP Engine ID is invalid, must be a valid number. diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/config/GeneralPropertiesConfigForm.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/config/GeneralPropertiesConfigForm.jsp index 30df9ef..136c37c 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/config/GeneralPropertiesConfigForm.jsp +++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/config/GeneralPropertiesConfigForm.jsp @@ -86,6 +86,17 @@ </table> </td> </tr> + <tr> + <td class="BlockLabel"><fmt:message key="admin.settings.AllowResourceGenericPropertiesUpgrade"/></td> + <td class="BlockContent"> + <table cellpadding="0" cellspacing="4" border="0"> + <tr> + <td align="left"><html:radio property="allowResourceGenericPropertiesUpgrade" value="true"/><fmt:message key="yesno.true"/></td> + <td align="left"><html:radio property="allowResourceGenericPropertiesUpgrade" value="false"/><fmt:message key="yesno.false"/></td> + </tr> + </table> + </td> + </tr>
<hq:authorization permission="superuser"> <tr>
commit 6c2472739d2df4b5a99f1e4fae22b945440dd5fd Author: Lukas Krejci lkrejci@redhat.com Date: Wed Jun 23 15:29:15 2010 +0200
Adding the ability of the server to alter/ignore some upgrade data.
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java new file mode 100644 index 0000000..825a616 --- /dev/null +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeRequest.java @@ -0,0 +1,55 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.clientapi.agent.upgrade; + +import org.rhq.core.domain.resource.ResourceUpgradeReport; + +/** + * Represents a request to upgrade a resource. + * + * @author Lukas Krejci + */ +public class ResourceUpgradeRequest extends ResourceUpgradeReport { + + private int resourceId; + + public ResourceUpgradeRequest() { + + } + + public ResourceUpgradeRequest(int resourceId, ResourceUpgradeReport report) { + setResourceId(resourceId); + setNewDescription(report.getNewDescription()); + setNewName(report.getNewName()); + setNewResourceKey(report.getNewResourceKey()); + } + + public int getResourceId() { + return resourceId; + } + + public void setResourceId(int resourceId) { + this.resourceId = resourceId; + } +} diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeResponse.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeResponse.java new file mode 100644 index 0000000..3faa9ef --- /dev/null +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/upgrade/ResourceUpgradeResponse.java @@ -0,0 +1,80 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.clientapi.agent.upgrade; + +import java.io.Serializable; + +/** + * Represents a response to a resource upgrade request. + * The upgraded* properties contain the values of the corresponding resource properties + * as they were stored on the server. + * + * @author Lukas Krejci + */ +public class ResourceUpgradeResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + private int resourceId; + + private String upgradedResourceName; + private String upgradedResourceKey; + private String upgradedResourceDescription; + + public ResourceUpgradeResponse() { + + } + + public int getResourceId() { + return resourceId; + } + + public void setResourceId(int resourceId) { + this.resourceId = resourceId; + } + + public String getUpgradedResourceName() { + return upgradedResourceName; + } + + public void setUpgradedResourceName(String upgradedResourceName) { + this.upgradedResourceName = upgradedResourceName; + } + + public String getUpgradedResourceKey() { + return upgradedResourceKey; + } + + public void setUpgradedResourceKey(String upgradedResourceKey) { + this.upgradedResourceKey = upgradedResourceKey; + } + + public String getUpgradedResourceDescription() { + return upgradedResourceDescription; + } + + public void setUpgradedResourceDescription(String upgradedResourceDescription) { + this.upgradedResourceDescription = upgradedResourceDescription; + } +} diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java index 61e5084..0622fc5 100644 --- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java @@ -29,6 +29,8 @@ import org.rhq.core.communications.command.annotation.Asynchronous; import org.rhq.core.communications.command.annotation.LimitedConcurrency; import org.rhq.core.communications.command.annotation.Timeout; import org.rhq.core.domain.discovery.AvailabilityReport; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeResponse; import org.rhq.core.clientapi.server.discovery.InventoryReport; import org.rhq.core.domain.discovery.MergeResourceResponse; import org.rhq.core.domain.discovery.ResourceSyncInfo; @@ -37,7 +39,6 @@ import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.ResourceErrorType; -import org.rhq.core.domain.resource.ResourceUpgradeReport;
/** * The interface to a JON server's resource discovery subsystem. @@ -139,11 +140,13 @@ public interface DiscoveryServerService {
/** * Upgrades the data of the resources according to the provided reports. + * The server is free to ignore or modify the requests and will provide the + * true changes made to the resources on the server-side in the result of this method. * - * @param upgradeReports contains the information about the upgrade of individual resources. - * @return true if the upgrade succeeded, false otherwise. + * @param upgradeRequests contains the information about the upgrade of individual resources. + * @return details on what resources have been upgraded with what data. */ - boolean upgradeResources(Set<ResourceUpgradeReport> upgradeReports); + Set<ResourceUpgradeResponse> upgradeResources(Set<ResourceUpgradeRequest> upgradeRequests);
/** * Gives the server a chance to apply any necessary post-processing that's needed for newly committed resources diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/sysconfig-data.xml b/modules/core/dbutils/src/main/scripts/dbsetup/sysconfig-data.xml index 26d648e..121e971 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/sysconfig-data.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/sysconfig-data.xml @@ -121,6 +121,9 @@ <!-- How old does availability have to be in order to get purged --> <data ID="55" PROPERTY_KEY="AVAILABILITY_PURGE" PROPERTY_VALUE="31536000000" DEFAULT_PROPERTY_VALUE="31536000000" FREAD_ONLY="FALSE"/> + + <data ID="56" PROPERTY_KEY="RESOURCE_GENERIC_PROPERTIES_UPGRADE" PROPERTY_VALUE="false" + DEFAULT_PROPERTY_VALUE="false" FREAD_ONLY="FALSE"/>
</table>
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index 71aa297..ad53803 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2994,6 +2994,14 @@ </schema-directSQL> </schemaSpec>
+ <schemaSpec version="2.88"> + <schema-directSQL> + <statement desc="Adding 'Allow Agent Plugins To Upgrade Generic Resource Properties' system configuration setting"> + INSERT INTO rhq_system_config (id, property_key, property_value, default_property_value) + VALUES (56, 'RESOURCE_GENERIC_PROPERTIES_UPGRADE', 'false', 'false') + </statement> + </schema-directSQL> + </schemaSpec> </dbupgrade> </target> </project> diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java index 979c456..0f9db04 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java @@ -41,7 +41,6 @@ public class ResourceUpgradeReport implements Serializable {
private static final long serialVersionUID = 1L;
- private int resourceId; private String newResourceKey; private String newName;
@@ -62,22 +61,6 @@ public class ResourceUpgradeReport implements Serializable {
}
- /** - * The server-side id of the resource being upgraded. - * The discovery components don't need to assign this value. - */ - public int getResourceId() { - return resourceId; - } - - /** - * The server-side id of the resource being upgraded. - * The discovery components don't need to assign this value. - */ - public void setResourceId(int resourceId) { - this.resourceId = resourceId; - } - public String getNewResourceKey() { return newResourceKey; } diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 6c3d26a..b5f5f00 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -55,6 +55,8 @@ import org.rhq.core.clientapi.agent.configuration.ConfigurationUtility; import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService; import org.rhq.core.clientapi.agent.discovery.InvalidPluginConfigurationClientException; import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeResponse; import org.rhq.core.clientapi.server.discovery.DiscoveryServerService; import org.rhq.core.clientapi.server.discovery.InvalidInventoryReportException; import org.rhq.core.clientapi.server.discovery.InventoryReport; @@ -92,7 +94,7 @@ import org.rhq.core.pc.plugin.CanonicalResourceKey; import org.rhq.core.pc.plugin.PluginComponentFactory; import org.rhq.core.pc.plugin.PluginManager; import org.rhq.core.pc.upgrade.ResourceUpgradeExecutor; -import org.rhq.core.pc.upgrade.ResourceUpgradeRequest; +import org.rhq.core.pc.upgrade.ResourceUpgradePendingRequest; import org.rhq.core.pc.util.DiscoveryComponentProxyFactory; import org.rhq.core.pc.util.FacetLockType; import org.rhq.core.pc.util.LoggingThreadFactory; @@ -1178,31 +1180,31 @@ public class InventoryManager extends AgentService implements ContainerService, return resourceContainer.updateAvailability(availabilityType); }
- public boolean mergeResourceFromUpgrade(Set<ResourceUpgradeReport> upgradeReports) { - boolean serverUpdated = false; + public void mergeResourceFromUpgrade(Set<ResourceUpgradeRequest> upgradeReports) { + Set<ResourceUpgradeResponse> serverUpdates = null; try { ServerServices serverServices = this.configuration.getServerServices(); if (serverServices != null) { DiscoveryServerService discoveryServerService = serverServices.getDiscoveryServerService();
- serverUpdated = discoveryServerService.upgradeResources(upgradeReports); + serverUpdates = discoveryServerService.upgradeResources(upgradeReports); } } catch (Exception e) { log.error("Failed to process resource upgrades on the server.", e); }
- if (serverUpdated) { - for (ResourceUpgradeReport upgradeReport : upgradeReports) { - String resourceKey = upgradeReport.getNewResourceKey(); - String name = upgradeReport.getNewName(); + if (serverUpdates != null) { + for (ResourceUpgradeResponse upgradeResponse : serverUpdates) { + String resourceKey = upgradeResponse.getUpgradedResourceKey(); + String name = upgradeResponse.getUpgradedResourceName(); //String version = upgradeReport.getNewVersion(); - String description = upgradeReport.getNewDescription(); + String description = upgradeResponse.getUpgradedResourceDescription(); //Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); //Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration();
//only bother if there's something to upgrade at all on this resource. if (resourceKey != null || name != null || description != null) { - ResourceContainer existingResourceContainer = getResourceContainer(upgradeReport.getResourceId()); + ResourceContainer existingResourceContainer = getResourceContainer(upgradeResponse.getResourceId()); if (existingResourceContainer != null) { Resource existingResource = existingResourceContainer.getResource();
@@ -1241,13 +1243,11 @@ public class InventoryManager extends AgentService implements ContainerService,
log.info(logMessage.toString()); } else { - log.error("Upgraded a resource that is not present on the agent. This should not happen. The id of the missing resource is " + upgradeReport.getResourceId()); + log.error("Upgraded a resource that is not present on the agent. This should not happen. The id of the missing resource is " + upgradeResponse.getResourceId()); } } } } - - return serverUpdated; }
public Resource mergeResourceFromDiscovery(Resource resource, Resource parent) throws PluginContainerException { @@ -2173,7 +2173,7 @@ public class InventoryManager extends AgentService implements ContainerService, }
if (resourceUpgradeExecutor.isEnabled()) { - resourceUpgradeExecutor.processAndQueue(new ResourceUpgradeRequest(newResources, context, parentResource.getId()), newResources); + resourceUpgradeExecutor.processAndQueue(new ResourceUpgradePendingRequest(newResources, context, parentResource.getId()), newResources); } } catch (Throwable e) { // TODO GH: Add server/parent - up/down semantics so this won't happen just because a server is not up diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java index bb20054..f344900 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java @@ -29,7 +29,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean;
@@ -37,6 +36,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
import org.rhq.core.clientapi.agent.PluginContainerException; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; import org.rhq.core.clientapi.server.discovery.InventoryReport; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; @@ -69,11 +69,11 @@ public class ResourceUpgradeExecutor implements Runnable {
private InventoryManager inventoryManager;
- private ConcurrentLinkedQueue<ResourceUpgradeReport> reports; + private ConcurrentLinkedQueue<ResourceUpgradeRequest> requests;
public ResourceUpgradeExecutor(InventoryManager inventoryManager) { this.inventoryManager = inventoryManager; - reports = new ConcurrentLinkedQueue<ResourceUpgradeReport>(); + requests = new ConcurrentLinkedQueue<ResourceUpgradeRequest>(); }
/** @@ -92,9 +92,9 @@ public class ResourceUpgradeExecutor implements Runnable { * @param discoveredResources the set of discovered resources that this method can optionally remove some elements from. */ public <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> processAndQueue( - ResourceUpgradeRequest<T> request, Set<Resource> discoveredResources) { + ResourceUpgradePendingRequest<T> request, Set<Resource> discoveredResources) {
- return enabled.get() ? executeResourceUpgradeAndStoreReport(request, discoveredResources) : null; + return enabled.get() ? executeResourceUpgradeAndStoreRequest(request, discoveredResources) : null; }
/** @@ -109,10 +109,10 @@ public class ResourceUpgradeExecutor implements Runnable { * all the upgrade requests. */ public void sendRequests() { - if (enabled.get() && reports.size() > 0) { - HashSet<ResourceUpgradeReport> currentCopy = new HashSet<ResourceUpgradeReport>(reports); + if (enabled.get() && requests.size() > 0) { + HashSet<ResourceUpgradeRequest> currentCopy = new HashSet<ResourceUpgradeRequest>(requests); inventoryManager.mergeResourceFromUpgrade(currentCopy); - reports.removeAll(currentCopy); + requests.removeAll(currentCopy); } }
@@ -148,7 +148,7 @@ public class ResourceUpgradeExecutor implements Runnable { this.enabled.set(false);
//clear up so that we don't hold unnecessary instances. - reports.clear(); + requests.clear();
if (log.isDebugEnabled()) { log.debug("Resource upgrade finished."); @@ -171,8 +171,8 @@ public class ResourceUpgradeExecutor implements Runnable { * * @throws PluginContainerException */ - private <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> executeResourceUpgradeAndStoreReport( - ResourceUpgradeRequest<T> request, Set<Resource> discoveredResources) { + private <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> executeResourceUpgradeAndStoreRequest( + ResourceUpgradePendingRequest<T> request, Set<Resource> discoveredResources) {
ResourceDiscoveryContext<T> discoveryContext = request.getDiscoveryContext(); Set<Resource> newResources = request.getDiscoveredResources(); @@ -267,14 +267,12 @@ public class ResourceUpgradeExecutor implements Runnable { results = inventoryManager.invokeDiscoveryComponentResourceUpgradeFacet(resourceType, discoveryComponent, siblingContexts, parentUpgradeContext, newResourceContexts);
- //now go through the results and upgrade the resources as needed. + //now go through the results and create the upgrade requests. for (Map.Entry<ResourceUpgradeContext<T>, ResourceUpgradeReport> upgradeEntry : results.entrySet()) { Resource siblingToUpgrade = siblingContextToResource.get(upgradeEntry.getKey()); - ResourceUpgradeReport newData = upgradeEntry.getValue(); + ResourceUpgradeRequest newData = new ResourceUpgradeRequest(siblingToUpgrade.getId(), upgradeEntry.getValue());
- //upgrade the data on the server first - newData.setResourceId(siblingToUpgrade.getId()); - reports.add(newData); + requests.add(newData);
//if there was a resource key upgrade, remove a resource with the same resource key //from the discovery results. Otherwise we'd end up with 2 sibling resources with diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradePendingRequest.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradePendingRequest.java new file mode 100644 index 0000000..1099643 --- /dev/null +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradePendingRequest.java @@ -0,0 +1,35 @@ +package org.rhq.core.pc.upgrade; + +import java.util.Set; + +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; + +/** + * This class is used to store the requests for resource upgrade that originate in + * the discovery workflow, but can only be executed after an inventory sync. + */ +public class ResourceUpgradePendingRequest<T extends ResourceComponent> { + private Set<Resource> discoveredResources; + private ResourceDiscoveryContext<T> discoveryContext; + private Integer parentResourceId; + + public ResourceUpgradePendingRequest(Set<Resource> discoveredResources, ResourceDiscoveryContext<T> discoveryContext, Integer parentResourceId) { + this.discoveredResources = discoveredResources; + this.discoveryContext = discoveryContext; + this.parentResourceId = parentResourceId; + } + + public Set<Resource> getDiscoveredResources() { + return discoveredResources; + } + + public ResourceDiscoveryContext<T> getDiscoveryContext() { + return discoveryContext; + } + + public Integer getParentResourceId() { + return parentResourceId; + } +} \ No newline at end of file diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeRequest.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeRequest.java deleted file mode 100644 index 25178ee..0000000 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeRequest.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.rhq.core.pc.upgrade; - -import java.util.Set; - -import org.rhq.core.domain.resource.Resource; -import org.rhq.core.pluginapi.inventory.ResourceComponent; -import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; - -/** - * This class is used to store the requests for resource upgrade that originate in - * the discovery workflow, but can only be executed after an inventory sync. - */ -public class ResourceUpgradeRequest<T extends ResourceComponent> { - private Set<Resource> discoveredResources; - private ResourceDiscoveryContext<T> discoveryContext; - private Integer parentResourceId; - - public ResourceUpgradeRequest(Set<Resource> discoveredResources, ResourceDiscoveryContext<T> discoveryContext, Integer parentResourceId) { - this.discoveredResources = discoveredResources; - this.discoveryContext = discoveryContext; - this.parentResourceId = parentResourceId; - } - - public Set<Resource> getDiscoveredResources() { - return discoveredResources; - } - - public ResourceDiscoveryContext<T> getDiscoveryContext() { - return discoveryContext; - } - - public Integer getParentResourceId() { - return parentResourceId; - } -} \ No newline at end of file diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java index 4341e3a..c3bdbf4 100644 --- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java @@ -37,15 +37,17 @@ import java.util.Set; import org.jmock.api.Invocation; import org.jmock.lib.action.CustomAction;
+import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeResponse; import org.rhq.core.clientapi.server.discovery.InventoryReport; import org.rhq.core.domain.discovery.ResourceSyncInfo; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; -import org.rhq.core.domain.resource.ResourceUpgradeReport;
/** - * + * This class represents a server side database store of the inventory for the purposes + * of the ResourceUpgradeTest unit test. * * @author Lukas Krejci */ @@ -89,28 +91,36 @@ public class FakeServerInventory { return new CustomAction("upgradeServerSideInventory") { @SuppressWarnings({"serial", "unchecked"}) public Object invoke(Invocation invocation) throws Throwable { - Set<ResourceUpgradeReport> reports = (Set<ResourceUpgradeReport>) invocation.getParameter(0); - - for (final ResourceUpgradeReport report : reports) { + Set<ResourceUpgradeRequest> requests = (Set<ResourceUpgradeRequest>) invocation.getParameter(0); + Set<ResourceUpgradeResponse> responses = new HashSet<ResourceUpgradeResponse>(); + + for (final ResourceUpgradeRequest request : requests) { Resource resource = findResource(platform, new Resource() { public int getId() { - return report.getResourceId(); + return request.getResourceId(); } }, ID_COMPARATOR); if (resource != null) { - if (report.getNewDescription() != null) { - resource.setDescription(report.getNewDescription()); + if (request.getNewDescription() != null) { + resource.setDescription(request.getNewDescription()); } - if (report.getNewName() != null) { - resource.setName(report.getNewName()); + if (request.getNewName() != null) { + resource.setName(request.getNewName()); }
- if (report.getNewResourceKey() != null) { - resource.setResourceKey(report.getNewResourceKey()); + if (request.getNewResourceKey() != null) { + resource.setResourceKey(request.getNewResourceKey()); } + + ResourceUpgradeResponse resp = new ResourceUpgradeResponse(); + resp.setResourceId(resource.getId()); + resp.setUpgradedResourceName(resource.getName()); + resp.setUpgradedResourceKey(resource.getResourceKey()); + resp.setUpgradedResourceDescription(resource.getDescription()); + responses.add(resp); } } - return true; + return responses; } }; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/RHQConstants.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/RHQConstants.java index 7bb1d72..fff7872 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/RHQConstants.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/RHQConstants.java @@ -110,5 +110,8 @@ public class RHQConstants {
// Syslog Actions enabled public static final String SyslogActionsEnabled = "CAM_SYSLOG_ACTIONS_ENABLED"; + + //allow plugin initiated resource name & description upgrades (resource key is always upgradable) + public static final String AllowResourceGenericPropertiesUpgrade = "RESOURCE_GENERIC_PROPERTIES_UPGRADE";
} \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index fd59590..329f476 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -20,8 +20,10 @@ package org.rhq.enterprise.server.discovery;
import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -43,6 +45,8 @@ import org.jetbrains.annotations.Nullable;
import org.rhq.core.clientapi.agent.PluginContainerException; import org.rhq.core.clientapi.agent.discovery.InvalidPluginConfigurationClientException; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeResponse; import org.rhq.core.clientapi.server.discovery.InvalidInventoryReportException; import org.rhq.core.clientapi.server.discovery.InventoryReport; import org.rhq.core.domain.auth.Subject; @@ -75,6 +79,7 @@ import org.rhq.enterprise.server.resource.ResourceAvailabilityManagerLocal; import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal; import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal; +import org.rhq.enterprise.server.system.SystemManagerLocal;
/** * SLSB that provides the interface point to the discovery subsystem for the UI layer and the discovery server service. @@ -107,6 +112,8 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot private SubjectManagerLocal subjectManager; @EJB private ProductVersionManagerLocal productVersionManager; + @EJB + private SystemManagerLocal systemManager;
public ResourceSyncInfo mergeInventoryReport(InventoryReport report) throws InvalidInventoryReportException { validateInventoryReport(report); @@ -407,20 +414,19 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot } }
- public boolean upgradeResources(Set<ResourceUpgradeReport> upgradeReports) { - for (ResourceUpgradeReport report : upgradeReports) { - Resource existingResource = this.entityManager.find(Resource.class, report.getResourceId()); + public Set<ResourceUpgradeResponse> upgradeResources(Set<ResourceUpgradeRequest> upgradeRequests) { + Set<ResourceUpgradeResponse> result = new HashSet<ResourceUpgradeResponse>(); + + boolean allowGenericPropertiesUpgrade = Boolean.parseBoolean(systemManager.getSystemConfiguration().getProperty(RHQConstants.AllowResourceGenericPropertiesUpgrade, "false")); + + for (ResourceUpgradeRequest request : upgradeRequests) { + Resource existingResource = this.entityManager.find(Resource.class, request.getResourceId()); if (existingResource != null) { - boolean changed = upgradeResource(existingResource, report); - if (changed) { - this.entityManager.merge(existingResource); - } - } else { - this.entityManager.getTransaction().setRollbackOnly(); - return false; + ResourceUpgradeResponse upgradedData = upgradeResource(existingResource, request, allowGenericPropertiesUpgrade); + result.add(upgradedData); } } - return true; + return result; }
/** @@ -471,40 +477,46 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot /** * @param existingResource * @param upgradeReport + * @param allowGenericPropertiesUpgrade name and description are only upgraded if this is true * @return true if the resource was changed, false otherwise */ - private boolean upgradeResource(Resource resource, ResourceUpgradeReport upgradeReport) { - if (resource != null) { - String resourceKey = upgradeReport.getNewResourceKey(); - String name = upgradeReport.getNewName(); + private ResourceUpgradeResponse upgradeResource(@NotNull Resource resource, ResourceUpgradeReport upgradeReport, boolean allowGenericPropertiesUpgrade) { + ResourceUpgradeResponse ret = new ResourceUpgradeResponse(); + ret.setResourceId(resource.getId()); + + String resourceKey = upgradeReport.getNewResourceKey(); + String name = upgradeReport.getNewName(); // String version = upgradeReport.getNewVersion(); - String description = upgradeReport.getNewDescription(); + String description = upgradeReport.getNewDescription(); // Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); // Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration(); + + if (resourceKey != null || name != null || description != null) { + StringBuilder logMessage = new StringBuilder("Resource [") + .append(resource.toString()).append("] upgraded its "); + + if (needsUpgrade(resource.getResourceKey(), resourceKey)) { + resource.setResourceKey(resourceKey); + logMessage.append("resourceKey, "); + } + ret.setUpgradedResourceKey(resource.getResourceKey()); + + if (allowGenericPropertiesUpgrade && needsUpgrade(resource.getName(), name)) { + resource.setName(name); + logMessage.append("name, "); + } + ret.setUpgradedResourceName(resource.getName());
- if (resourceKey != null || name != null || description != null) { - StringBuilder logMessage = new StringBuilder("Resource [") - .append(resource.toString()).append("] upgraded its "); - - if (needsUpgrade(resource.getResourceKey(), resourceKey)) { - resource.setResourceKey(resourceKey); - logMessage.append("resourceKey, "); - } - - if (needsUpgrade(resource.getName(), name)) { - resource.setName(name); - logMessage.append("name, "); - } - // if (version != null) { // changed = updateResourceVersion(resource, version) || changed; // } - - if (needsUpgrade(resource.getDescription(), description)) { - resource.setDescription(description); - logMessage.append("description, "); - } - + + if (allowGenericPropertiesUpgrade && needsUpgrade(resource.getDescription(), description)) { + resource.setDescription(description); + logMessage.append("description, "); + } + ret.setUpgradedResourceDescription(resource.getDescription()); + // if (pluginConfiguration != null) { // if (!equalOrNull(pluginConfiguration, resource.getPluginConfiguration())) { // log.info("Resource [" + resource + "] upgraded its plugin configuration from [" + @@ -525,16 +537,13 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot // resource.setResourceConfiguration(resourceConfiguration); // } // } - - logMessage.replace(logMessage.length() - 1, logMessage.length(), - "to become [").append(resource.toString()).append("]");
- log.info(logMessage.toString()); - - return true; - } + logMessage.replace(logMessage.length() - 1, logMessage.length(), + "to become [").append(resource.toString()).append("]"); + + log.info(logMessage.toString()); } - return false; + return ret; }
private void validateInventoryReport(InventoryReport report) throws InvalidInventoryReportException { @@ -651,9 +660,21 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot */ ResourceType resourceType = resource.getResourceType(); Resource parent = resource; + Subject overlord = subjectManager.getOverlord(); while (parent != null && existingResource == null) { parent = parent.getParentResource(); - existingResource = resourceManager.getResourceByParentAndKey(subjectManager.getOverlord(), parent, + //check if the parent itself is inventoried. This might not be the case + //during initial sync-up for resource upgrade. + Resource existingParent = null; + if (parent != null) { + existingParent = entityManager.find(Resource.class, parent.getId()); + if (existingParent == null) { + //well, this parent is not known to the server, so there's no + //point in trying to find a child of it... + continue; + } + } + existingResource = resourceManager.getResourceByParentAndKey(overlord, existingParent, resource.getResourceKey(), resourceType.getPlugin(), resourceType.getName()); }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java index af518eb..c9208fc 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java @@ -29,6 +29,8 @@ import org.jetbrains.annotations.NotNull;
import org.rhq.core.clientapi.agent.PluginContainerException; import org.rhq.core.clientapi.agent.discovery.InvalidPluginConfigurationClientException; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeResponse; import org.rhq.core.clientapi.server.discovery.InvalidInventoryReportException; import org.rhq.core.clientapi.server.discovery.InventoryReport; import org.rhq.core.domain.auth.Subject; @@ -181,9 +183,11 @@ public interface DiscoveryBossLocal extends DiscoveryBossRemote {
/** * Upgrades the data of the resources according to the provided reports. + * The server is free to ignore or modify the requests and will provide the + * true changes made to the resources on the server-side in the result of this method. * - * @param upgradeReports contains the information about the upgrade of individual resources. - * @return true if the upgrade succeeded, false otherwise. + * @param upgradeRequests contains the information about the upgrade of individual resources. + * @return details on what resources have been upgraded with what data. */ - boolean upgradeResources(Set<ResourceUpgradeReport> upgradeReports); + Set<ResourceUpgradeResponse> upgradeResources(Set<ResourceUpgradeRequest> upgradeRequest); } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java index 0f90cdc..5dbe59a 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java @@ -25,6 +25,8 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest; +import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeResponse; import org.rhq.core.clientapi.server.discovery.DiscoveryServerService; import org.rhq.core.clientapi.server.discovery.InvalidInventoryReportException; import org.rhq.core.clientapi.server.discovery.InventoryReport; @@ -177,9 +179,9 @@ public class DiscoveryServerServiceImpl implements DiscoveryServerService { return discoveryBoss.updateResourceVersion(resourceId, version); }
- public boolean upgradeResources(Set<ResourceUpgradeReport> upgradeReports) { + public Set<ResourceUpgradeResponse> upgradeResources(Set<ResourceUpgradeRequest> upgradeRequests) { DiscoveryBossLocal discoveryBoss = LookupUtil.getDiscoveryBoss(); - return discoveryBoss.upgradeResources(upgradeReports); + return discoveryBoss.upgradeResources(upgradeRequests); }
private static Resource convertToPojoResource(Resource resource, boolean includeDescendants) {
commit a479fd3591a15b7422b378a000f213a21b9bf750 Merge: ab45b75... f595c48... Author: Lukas Krejci lkrejci@redhat.com Date: Fri Jun 18 21:19:23 2010 +0200
Merge branch 'release-3.0.0' into resource-upgrade
commit ab45b7518ec6b740899c694c3229746cd0490fd6 Author: Lukas Krejci lkrejci@redhat.com Date: Fri Jun 18 20:25:56 2010 +0200
Basic unit tests of the resource upgrade workflow along with some minor changes in the PC to handle the hardcoded test platform in a normal connected-like scenarios.
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/metadata/PluginMetadataManager.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/metadata/PluginMetadataManager.java index 63072db..0c5e0b6 100644 --- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/metadata/PluginMetadataManager.java +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/metadata/PluginMetadataManager.java @@ -55,7 +55,7 @@ public class PluginMetadataManager { private Object typesLock = new Object();
private Map<String, PluginMetadataParser> parsersByPlugin = new HashMap<String, PluginMetadataParser>(); - + public PluginMetadataManager() { }
@@ -177,6 +177,9 @@ public class PluginMetadataManager {
@Nullable public ResourceType getType(ResourceType resourceType) { + if (TEST_PLATFORM_TYPE.equals(resourceType)) { + return TEST_PLATFORM_TYPE; + } return getType(resourceType.getName(), resourceType.getPlugin()); }
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index dbee063..1433120 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -1369,12 +1369,6 @@ public class InventoryManager extends AgentService implements ContainerService, resourceContainer.setSynchronizationState(ResourceContainer.SynchronizationState.SYNCHRONIZED); } this.resourceContainers.put(resource.getUuid(), resourceContainer); - if (resource.getParentResource() == null) { - // no parent - must be the top level platform - do some things needed for unit tests - if (this.platform.getResourceType().equals(PluginMetadataManager.TEST_PLATFORM_TYPE)) { - resourceContainer.setResourceComponent(createTestPlatformComponent()); - } - } } else { // container already exists, but make sure the classloader exists too if (resourceContainer.getResourceClassLoader() == null) { @@ -1800,6 +1794,13 @@ public class InventoryManager extends AgentService implements ContainerService, Set<DiscoveredResourceDetails> allDiscoveredPlatforms = new HashSet<DiscoveredResourceDetails>(2);
if ((platformTypes != null) && (platformTypes.size() > 0)) { + + //check for fake testing type. If the test platform type is being used, it is always going to be + //the sole platform type available. + if (platformTypes.size() == 1 && platformTypes.contains(PluginMetadataManager.TEST_PLATFORM_TYPE)) { + return getTestPlatform(); + } + // Go through all the platform types that are supported and see if they can detect our platform. for (ResourceType platformType : platformTypes) { try { @@ -1828,7 +1829,7 @@ public class InventoryManager extends AgentService implements ContainerService, .error("Missing platform plugin(s) - falling back to dummy platform impl; this should only occur in tests!"); // TODO: Set sysprop (e.g. rhq.test.mode=true) in integration tests, // and throw a runtime exception here if that sysprop is not set. - return createTestPlatform(); + return getTestPlatform(); }
if (allDiscoveredPlatforms.isEmpty()) { @@ -1870,9 +1871,13 @@ public class InventoryManager extends AgentService implements ContainerService, * resource. This is normally only used during tests. * @return A dummy platform for testing purposes only. */ - private Resource createTestPlatform() { + private Resource getTestPlatform() { ResourceType type = PluginContainer.getInstance().getPluginManager().getMetadataManager().addTestPlatformType(); + if (this.platform != null && this.platform.getResourceType() == type) { + return this.platform; + } Resource platform = new Resource("testkey" + configuration.getContainerName(), "testplatform", type); + platform.setUuid(UUID.randomUUID().toString()); platform.setAgent(this.agent); return platform; } diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginComponentFactory.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginComponentFactory.java index 4176353..b9d9cf3 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginComponentFactory.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginComponentFactory.java @@ -30,6 +30,7 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.clientapi.agent.PluginContainerException; import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager; +import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.pc.ContainerService; @@ -39,6 +40,7 @@ import org.rhq.core.pc.inventory.InventoryManager; import org.rhq.core.pc.inventory.ResourceContainer; import org.rhq.core.pluginapi.inventory.ClassLoaderFacet; import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
/** @@ -129,6 +131,19 @@ public class PluginComponentFactory implements ContainerService { */ public ResourceComponent buildResourceComponent(Resource resource) throws PluginContainerException { ResourceType resourceType = resource.getResourceType(); + if (PluginMetadataManager.TEST_PLATFORM_TYPE.equals(resourceType)) { + return new ResourceComponent() { + public AvailabilityType getAvailability() { + return AvailabilityType.UP; + } + + public void start(ResourceContext context) { + } + + public void stop() { + } + }; + } String className = getPluginManager().getMetadataManager().getComponentClass(resourceType); ClassLoader resourceClassloader = getResourceClassloader(resource); ResourceComponent component = (ResourceComponent) instantiateClass(resourceClassloader, className); diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java new file mode 100644 index 0000000..4341e3a --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/FakeServerInventory.java @@ -0,0 +1,272 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.pc.upgrade; + +import static org.testng.Assert.fail; + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import org.jmock.api.Invocation; +import org.jmock.lib.action.CustomAction; + +import org.rhq.core.clientapi.server.discovery.InventoryReport; +import org.rhq.core.domain.discovery.ResourceSyncInfo; +import org.rhq.core.domain.resource.InventoryStatus; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.domain.resource.ResourceUpgradeReport; + +/** + * + * + * @author Lukas Krejci + */ +public class FakeServerInventory { + + private Resource platform; + private Map<String, Resource> resourceStore = new HashMap<String, Resource>(); + private int counter; + + private static final Comparator<Resource> ID_COMPARATOR = new Comparator<Resource>() { + public int compare(Resource o1, Resource o2) { + return o1.getId() - o2.getId(); + } + }; + + private static final Comparator<Resource> RESOURCE_TYPE_COMPARATOR = new Comparator<Resource>() { + public int compare(Resource o1, Resource o2) { + return o1.getResourceType().equals(o2.getResourceType()) ? 0 : o1.getId() - o2.getId(); + } + }; + + //need to synchronize, because resource upgrade is async and can overlap with + //resource discovery. + public synchronized CustomAction mergeInventoryReport(final InventoryStatus requiredInventoryStatus) { + return new CustomAction("updateServerSideInventory") { + public Object invoke(Invocation invocation) throws Throwable { + InventoryReport inventoryReport = (InventoryReport) invocation.getParameter(0); + + for(Resource res : inventoryReport.getAddedRoots()) { + if (res.getParentResource() == Resource.ROOT) { + platform = fakePersist(res, requiredInventoryStatus, new HashSet<String>()); + break; + } + } + return getSyncInfo(); + } + }; + } + + public synchronized CustomAction upgradeResources() { + return new CustomAction("upgradeServerSideInventory") { + @SuppressWarnings({"serial", "unchecked"}) + public Object invoke(Invocation invocation) throws Throwable { + Set<ResourceUpgradeReport> reports = (Set<ResourceUpgradeReport>) invocation.getParameter(0); + + for (final ResourceUpgradeReport report : reports) { + Resource resource = findResource(platform, new Resource() { + public int getId() { + return report.getResourceId(); + } + }, ID_COMPARATOR); + if (resource != null) { + if (report.getNewDescription() != null) { + resource.setDescription(report.getNewDescription()); + } + if (report.getNewName() != null) { + resource.setName(report.getNewName()); + } + + if (report.getNewResourceKey() != null) { + resource.setResourceKey(report.getNewResourceKey()); + } + } + } + return true; + } + }; + } + + public synchronized CustomAction getResources() { + return new CustomAction("getResources") { + @SuppressWarnings("unchecked") + public Object invoke(Invocation invocation) throws Throwable { + Set<Integer> resourceIds = (Set<Integer>)invocation.getParameter(0); + boolean includeDescendants = (Boolean) invocation.getParameter(1); + + return getResources(resourceIds, includeDescendants); + } + }; + } + + @SuppressWarnings("serial") + public synchronized Set<Resource> findResourcesByType(final ResourceType type) { + Set<Resource> result = new HashSet<Resource>(); + if (platform != null) { + findResources(platform, new Resource() { + public ResourceType getResourceType() { + return type; + } + }, result, RESOURCE_TYPE_COMPARATOR); + } + return result; + } + + @SuppressWarnings("serial") + private Set<Resource> getResources(Set<Integer> resourceIds, boolean includeDescendants) { + Set<Resource> result = new HashSet<Resource>(); + + for(final Integer id : resourceIds) { + Resource r = findResource(platform, new Resource() { + public int getId() { + return id; + } + }, ID_COMPARATOR); + if (r != null) { + result.add(r); + + if (includeDescendants) { + for(Resource child : r.getChildResources()) { + result.addAll(getResources(Collections.singleton(child.getId()), true)); + } + } + } + } + + return result; + } + + private Resource fakePersist(Resource agentSideResource, InventoryStatus requiredInventoryStatus, Set<String> inProgressUUIds) { + Resource persisted = resourceStore.get(agentSideResource.getUuid()); + if (!inProgressUUIds.add(agentSideResource.getUuid())) { + return persisted; + } + if (persisted == null) { + persisted = new Resource(); + persisted.setId(++counter); + persisted.setUuid(agentSideResource.getUuid()); + resourceStore.put(persisted.getUuid(), persisted); + } + persisted.setAgent(agentSideResource.getAgent()); + persisted.setCurrentAvailability(agentSideResource.getCurrentAvailability()); + persisted.setDescription(agentSideResource.getDescription()); + persisted.setName(agentSideResource.getName()); + persisted.setPluginConfiguration(agentSideResource.getPluginConfiguration().clone()); + persisted.setResourceConfiguration(agentSideResource.getResourceConfiguration().clone()); + persisted.setVersion(agentSideResource.getVersion()); + persisted.setInventoryStatus(requiredInventoryStatus); + persisted.setResourceKey(agentSideResource.getResourceKey()); + persisted.setResourceType(agentSideResource.getResourceType()); + + Resource parent = agentSideResource.getParentResource(); + if (parent != null && parent != Resource.ROOT) { + persisted.setParentResource(fakePersist(agentSideResource.getParentResource(), requiredInventoryStatus, inProgressUUIds)); + } else { + persisted.setParentResource(parent); + } + + Set<Resource> childResources = new HashSet<Resource>(); + persisted.setChildResources(childResources); + for(Resource child : agentSideResource.getChildResources()) { + childResources.add(fakePersist(child, requiredInventoryStatus, inProgressUUIds)); + } + + inProgressUUIds.remove(agentSideResource.getUuid()); + + return persisted; + } + + private ResourceSyncInfo getSyncInfo() { + return platform != null ? convert(platform) : null; + } + + private static ResourceSyncInfo convert(Resource root) { + try { + ResourceSyncInfo ret = new ResourceSyncInfo(); + + Class<ResourceSyncInfo> clazz = ResourceSyncInfo.class; + + getPrivateField(clazz, "id").set(ret, root.getId()); + getPrivateField(clazz, "uuid").set(ret, root.getUuid()); + getPrivateField(clazz, "mtime").set(ret, root.getMtime()); + getPrivateField(clazz, "inventoryStatus").set(ret, root.getInventoryStatus()); + getPrivateField(clazz, "parent").set(ret, null); + + Set<ResourceSyncInfo> children = new LinkedHashSet<ResourceSyncInfo>(); + for(Resource child : root.getChildResources()) { + ResourceSyncInfo syncChild = convert(child); + getPrivateField(clazz, "parent").set(syncChild, ret); + + children.add(convert(child)); + } + getPrivateField(clazz, "childSyncInfos").set(ret, children); + + return ret; + } catch (Exception e) { + fail("Failed to convert resource " + root + " to a ResourceSyncInfo. This should not happen.", e); + return null; + } + } + + private static Field getPrivateField(Class<?> clazz, String fieldName) throws NoSuchFieldException { + Field field = clazz.getDeclaredField(fieldName); + if (!field.isAccessible()) { + field.setAccessible(true); + } + + return field; + } + + private static Resource findResource(Resource root, Resource template, Comparator<Resource> comparator) { + if (root == null) return null; + if (comparator.compare(root, template) == 0) { + return root; + } else { + for(Resource child : root.getChildResources()) { + Resource found = findResource(child, template, comparator); + if (found != null) return found; + } + } + + return null; + } + + private static void findResources(Resource root, Resource template, Set<Resource> result, Comparator<Resource> comparator) { + if (root == null) return; + if (comparator.compare(root, template) == 0) { + result.add(root); + } else { + for(Resource child : root.getChildResources()) { + findResources(child, template, result, comparator); + } + } + } +} diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java new file mode 100644 index 0000000..46d069c --- /dev/null +++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/upgrade/ResourceUpgradeTest.java @@ -0,0 +1,345 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.pc.upgrade; + +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Collections; +import java.util.Set; + +import org.apache.commons.io.FileUtils; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import org.rhq.core.clientapi.server.bundle.BundleServerService; +import org.rhq.core.clientapi.server.configuration.ConfigurationServerService; +import org.rhq.core.clientapi.server.content.ContentServerService; +import org.rhq.core.clientapi.server.core.CoreServerService; +import org.rhq.core.clientapi.server.discovery.DiscoveryServerService; +import org.rhq.core.clientapi.server.discovery.InventoryReport; +import org.rhq.core.clientapi.server.event.EventServerService; +import org.rhq.core.clientapi.server.inventory.ResourceFactoryServerService; +import org.rhq.core.clientapi.server.measurement.MeasurementServerService; +import org.rhq.core.clientapi.server.operation.OperationServerService; +import org.rhq.core.domain.resource.InventoryStatus; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.pc.PluginContainer; +import org.rhq.core.pc.PluginContainerConfiguration; +import org.rhq.core.pc.ServerServices; +import org.rhq.core.pc.inventory.InventoryManager; +import org.rhq.core.pc.inventory.ResourceContainer; +import org.rhq.core.pc.plugin.FileSystemPluginFinder; + +/** + * Test cases for resource upgrade. + * + * @author Lukas Krejci + */ +public class ResourceUpgradeTest { + + private static final String PLUGIN_V1_FILENAME = "resource-upgrade-test-plugin-1.0.0.jar"; + private static final String PLUGIN_V2_FILENAME = "resource-upgrade-test-plugin-2.0.0.jar"; + + private static final String PLUGINS_DIR_NAME = "plugins"; + private static final String DATA_DIR_NAME = "data"; + private static final String TMP_DIR_NAME = "tmp"; + + private File tmpDir; + private File pluginDir; + private File dataDir; + + private BundleServerService currentBundleServerService; + private ConfigurationServerService currentConfigurationServerService; + private ContentServerService currentContentServerService; + private CoreServerService currentCoreServerService; + private DiscoveryServerService currentDiscoveryServerService; + private EventServerService currentEventServerService; + private MeasurementServerService currentMeasurementServerService; + private OperationServerService currentOperationServerService; + private ResourceFactoryServerService currentResourceFactoryServerService; + + private FakeServerInventory currentServerSideInventory; + + @AfterClass + public void undeployPlugins() throws IOException { + FileUtils.deleteDirectory(tmpDir); + } + + @BeforeClass + public void sanityCheck() { + verifyPluginExists(PLUGIN_V1_FILENAME); + verifyPluginExists(PLUGIN_V2_FILENAME); + } + + @BeforeClass + public void init() { + tmpDir = getTmpDirectory(); + pluginDir = new File(tmpDir, PLUGINS_DIR_NAME); + assertTrue(pluginDir.mkdir(), "Could not create plugin deploy directory."); + dataDir = new File(tmpDir, DATA_DIR_NAME); + assertTrue(dataDir.mkdir(), "Could not create plugin container data directory."); + } + + @Test + public void testInitialSyncAndDiscoveryWithoutCommit() throws Exception { + testInitialSyncAndDiscovery(InventoryStatus.NEW); + } + + @Test(dependsOnMethods = "testInitialSyncAndDiscoveryWithoutCommit") + public void testIgnoreUncommittedResources() throws Exception { + TestPayload testNoChange = new TestPayload() { + public void test(Resource discoveredResource) { + assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); + assertEquals(discoveredResource.getName(), "resource-name-v1"); + assertEquals(discoveredResource.getDescription(), "resource-description-v1"); + } + + @SuppressWarnings("unchecked") + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineIgnoredExpectations(this); + + between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); + will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + + allowing(currentDiscoveryServerService).getResources(with(any(Set.class)), with(any(boolean.class))); + will(currentServerSideInventory.getResources()); + } + }; + } + }; + + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, testNoChange); + } + + //make the tests run serially, so that they don't overwrite the currentServerSideInventory + //variable concurrently + @Test(dependsOnMethods = "testIgnoreUncommittedResources") + public void testInitialSyncAndDiscoveryWithCommit() throws Exception { + testInitialSyncAndDiscovery(InventoryStatus.COMMITTED); + } + + @Test(dependsOnMethods = "testInitialSyncAndDiscoveryWithCommit") + public void testUpgradeData() throws Exception { + //we are keeping the currentServerSideInventory from the previous test + executeTestWithPlugins(Collections.singleton(PLUGIN_V2_FILENAME), false, new TestPayload() { + public void test(Resource discoveredResource) { + assertEquals(discoveredResource.getResourceKey(), "resource-key-v2"); + assertEquals(discoveredResource.getName(), "resource-name-v2"); + assertEquals(discoveredResource.getDescription(), "resource-description-v2"); + + ResourceContainer container = PluginContainer.getInstance().getInventoryManager().getResourceContainer(discoveredResource); + File dataDir = container.getResourceContext().getDataDirectory(); + + File marker = new File(dataDir, "upgrade-succeeded"); + + assertTrue(marker.exists(), "The upgrade success marker file wasn't found. This means the upgrade didn't actually run."); + } + + @SuppressWarnings("unchecked") + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineIgnoredExpectations(this); + + between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); + will(currentServerSideInventory.mergeInventoryReport(InventoryStatus.COMMITTED)); + + oneOf(currentDiscoveryServerService).upgradeResources(with(any(Set.class))); + will(currentServerSideInventory.upgradeResources()); + + allowing(currentDiscoveryServerService).getResources(with(any(Set.class)), with(any(boolean.class))); + will(currentServerSideInventory.getResources()); + } + }; + } + }); + } + + private void testInitialSyncAndDiscovery(final InventoryStatus requiredInventoryStatus) throws Exception { + currentServerSideInventory = new FakeServerInventory(); + executeTestWithPlugins(Collections.singleton(PLUGIN_V1_FILENAME), true, new TestPayload() { + public void test(Resource discoveredResource) { + assertEquals(discoveredResource.getResourceKey(), "resource-key-v1"); + assertEquals(discoveredResource.getName(), "resource-name-v1"); + assertEquals(discoveredResource.getDescription(), "resource-description-v1"); + } + + @SuppressWarnings("unchecked") + public Expectations getExpectations(Mockery context) throws Exception { + return new Expectations() { + { + defineIgnoredExpectations(this); + + between(1, 4).of(currentDiscoveryServerService).mergeInventoryReport(with(any(InventoryReport.class))); + will(currentServerSideInventory.mergeInventoryReport(requiredInventoryStatus)); + + allowing(currentDiscoveryServerService).getResources(with(any(Set.class)), with(any(boolean.class))); + will(currentServerSideInventory.getResources()); + } + }; + } + }); + + } + + private PluginContainerConfiguration createPluginContainerConfiguration(Mockery context) throws Exception { + PluginContainerConfiguration conf = new PluginContainerConfiguration(); + + conf.setPluginDirectory(new File(tmpDir, PLUGINS_DIR_NAME)); + conf.setDataDirectory(new File(tmpDir, DATA_DIR_NAME)); + conf.setTemporaryDirectory(new File(tmpDir, TMP_DIR_NAME)); + conf.setInsideAgent(true); //pc must think it's inside an agent so that it persists the inventory between restarts + conf.setPluginFinder(new FileSystemPluginFinder(conf.getPluginDirectory())); + conf.setCreateResourceClassloaders(false); + + currentBundleServerService = context.mock(BundleServerService.class); + currentConfigurationServerService = context.mock(ConfigurationServerService.class); + currentContentServerService = context.mock(ContentServerService.class); + currentCoreServerService = context.mock(CoreServerService.class); + currentDiscoveryServerService = context.mock(DiscoveryServerService.class); + currentEventServerService = context.mock(EventServerService.class); + currentMeasurementServerService = context.mock(MeasurementServerService.class); + currentOperationServerService = context.mock(OperationServerService.class); + currentResourceFactoryServerService = context.mock(ResourceFactoryServerService.class); + + ServerServices serverServices = new ServerServices(); + serverServices.setBundleServerService(currentBundleServerService); + serverServices.setConfigurationServerService(currentConfigurationServerService); + serverServices.setContentServerService(currentContentServerService); + serverServices.setCoreServerService(currentCoreServerService); + serverServices.setDiscoveryServerService(currentDiscoveryServerService); + serverServices.setEventServerService(currentEventServerService); + serverServices.setMeasurementServerService(currentMeasurementServerService); + serverServices.setOperationServerService(currentOperationServerService); + serverServices.setResourceFactoryServerService(currentResourceFactoryServerService); + + conf.setServerServices(serverServices); + + return conf; + } + + /** + * @param pluginResourcePath + */ + private void verifyPluginExists(String pluginResourcePath) { + URL url = getClass().getResource(pluginResourcePath); + + File pluginFile = FileUtils.toFile(url); + + assertTrue(pluginFile.exists(), pluginFile.getAbsoluteFile() + " plugin jar could not be found."); + } + + private void copyPlugin(String pluginResourcePath, File pluginDirectory) throws IOException { + URL pluginUrl = getClass().getResource(pluginResourcePath); + + File pluginFile = new File(pluginResourcePath); + String pluginFileName = pluginFile.getName(); + + FileUtils.copyURLToFile(pluginUrl, new File(pluginDirectory, pluginFileName)); + } + + private static File getTmpDirectory() { + File ret = new File(System.getProperty("java.io.tmpdir"), "resource-upgrade-test" + System.currentTimeMillis()); + + while (ret.exists() || !ret.mkdir()) { + ret = new File(System.getProperty("java.io.tmpdir"), "resource-upgrade-test" + System.currentTimeMillis()); + } + + return ret; + } + + private interface TestPayload { + Expectations getExpectations(Mockery context) throws Exception; + void test(Resource resourceUpgradeTestResource); + } + + private Set<Resource> getTestingResources() { + ResourceType resType = PluginContainer.getInstance().getPluginManager().getMetadataManager().getType("Resource", "ResourceUpgradeTest"); + + return currentServerSideInventory.findResourcesByType(resType); + } + + private void executeTestWithPlugins(Set<String> pluginResourcePaths, boolean clearInventoryDat, TestPayload test) throws Exception { + FileUtils.cleanDirectory(new File(tmpDir, PLUGINS_DIR_NAME)); + + for(String pluginResourcePath : pluginResourcePaths) { + copyPlugin(pluginResourcePath, pluginDir); + } + + Mockery context = new Mockery(); + + PluginContainerConfiguration pcConfig = createPluginContainerConfiguration(context); + + if (clearInventoryDat) { + File inventoryDat = new File(pcConfig.getDataDirectory(), "inventory.dat"); + inventoryDat.delete(); + } + + context.checking(test.getExpectations(context)); + + PluginContainer.getInstance().setConfiguration(pcConfig); + PluginContainer.getInstance().initialize(); + + //give the pc the time to finish resource upgrade + Thread.sleep(1000); + + //execute full discovery + InventoryManager im = PluginContainer.getInstance().getInventoryManager(); + im.executeServerScanImmediately(); + im.executeServiceScanImmediately(); + + Set<Resource> resources = getTestingResources(); + + assertEquals(resources.size(), 1, "There should be only a single testing resource but " + resources + " were found."); + + Resource discoveredResource = resources.iterator().next(); + + test.test(discoveredResource); + + PluginContainer.getInstance().shutdown(); + + context.assertIsSatisfied(); + } + + private void defineIgnoredExpectations(Expectations expectations) { + expectations.ignoring(currentBundleServerService); + expectations.ignoring(currentConfigurationServerService); + expectations.ignoring(currentContentServerService); + expectations.ignoring(currentCoreServerService); + expectations.ignoring(currentEventServerService); + expectations.ignoring(currentMeasurementServerService); + expectations.ignoring(currentOperationServerService); + expectations.ignoring(currentResourceFactoryServerService); + } +} diff --git a/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-1.0.0.jar b/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-1.0.0.jar new file mode 100644 index 0000000..33a79c0 Binary files /dev/null and b/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-1.0.0.jar differ diff --git a/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar b/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar new file mode 100644 index 0000000..412ae00 Binary files /dev/null and b/modules/core/plugin-container/src/test/resources/org/rhq/core/pc/upgrade/resource-upgrade-test-plugin-2.0.0.jar differ
commit 8dae62e89bc703cf2b8e16272b8d9ebc912606dd Author: Lukas Krejci lkrejci@redhat.com Date: Fri Jun 18 20:22:33 2010 +0200
Correctly handle the upgrade sync up when the agent is connected to the server for the very first time.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 54c6bcc..dbee063 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -900,7 +900,6 @@ public class InventoryManager extends AgentService implements ContainerService, */ public boolean handleReport(InventoryReport report, boolean forceServerRoundtrip) { if (!configuration.isInsideAgent()) { - //TODO how does resource upgrade behave in the embedded scenario? return true; }
@@ -943,7 +942,14 @@ public class InventoryManager extends AgentService implements ContainerService, return false; }
- synchInventory(syncInfo); + //sync info can be null if the server hasn't received a full inventory report + //from us yet. This can happen if this method is being invoked from inside the + //resource upgrade executor to sync up with the server side inventory *JUST AFTER* + //this agent registered with the server for the very first time. In that case + //the server hasn't received any info from us yet. + if (syncInfo != null) { + synchInventory(syncInfo); + }
return true; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index 76d6265..fd59590 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -156,7 +156,13 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot
// Prepare the ResourceSyncInfo tree which contains all the info the PC needs to sync itself up with us. Resource platform = this.resourceManager.getPlatform(knownAgent); - ResourceSyncInfo syncInfo = this.entityManager.find(ResourceSyncInfo.class, platform.getId()); + + //the platform can be null in only one scenario.. a brand new agent has connected to the server + //and that agent is currently trying to upgrade its resources. For that it asks us to send down + //the current inventory on the server side. But at this point there isn't any since that very + //agent just registered and is starting up for the very first time and therefore hasn't had + //a chance yet to send us its full inventory report. + ResourceSyncInfo syncInfo = platform != null ? this.entityManager.find(ResourceSyncInfo.class, platform.getId()) : null;
if (log.isDebugEnabled()) { log.debug("Inventory merge completed in (" + (System.currentTimeMillis() - start) + ")ms");
commit a9622206993586ce28df9e586206cbf981cc7c3b Author: Lukas Krejci lkrejci@redhat.com Date: Fri May 28 18:09:24 2010 +0200
Filter out not-commited resources from the upgrade process.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java index 3397e76..bb20054 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java @@ -26,6 +26,7 @@ package org.rhq.core.pc.upgrade; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -37,6 +38,7 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.clientapi.agent.PluginContainerException; import org.rhq.core.clientapi.server.discovery.InventoryReport; +import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.ResourceUpgradeReport; @@ -203,6 +205,15 @@ public class ResourceUpgradeExecutor implements Runnable { Set<Resource> siblings = parentResource == null ? Collections.singleton(inventoryManager.getPlatform()) : inventoryManager.getResourcesWithType(resourceType, parentResource.getChildResources());
+ //filter out not committed resources + //XXX what about uninventoried or ignored ones? is it correct to not upgrade those? + Iterator<Resource> siblingsIterator = siblings.iterator(); + while (siblingsIterator.hasNext()) { + if (siblingsIterator.next().getInventoryStatus() != InventoryStatus.COMMITTED) { + siblingsIterator.remove(); + } + } + //get the upgrade context of the parent resource so that it can be passed to the upgrade method //of the discovery component. ResourceUpgradeContext<?> parentUpgradeContext = null;
commit df4ffc41f2554332ba870eaeb69e20017ea25240 Author: Lukas Krejci lkrejci@redhat.com Date: Fri May 28 18:08:53 2010 +0200
Improve resource upgrade logging on both agent and server side.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index ba5f316..54c6bcc 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -1194,36 +1194,50 @@ public class InventoryManager extends AgentService implements ContainerService, //Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); //Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration();
- ResourceContainer existingResourceContainer = getResourceContainer(upgradeReport.getResourceId()); - if (existingResourceContainer != null) { - Resource existingResource = existingResourceContainer.getResource(); - if (resourceKey != null) { - existingResource.setResourceKey(resourceKey); - } - - if (name != null) { - existingResource.setName(name); - } - -// if (version != null) { -// existingResource.setVersion(version); -// } - - if (description != null) { - existingResource.setDescription(description); + //only bother if there's something to upgrade at all on this resource. + if (resourceKey != null || name != null || description != null) { + ResourceContainer existingResourceContainer = getResourceContainer(upgradeReport.getResourceId()); + if (existingResourceContainer != null) { + Resource existingResource = existingResourceContainer.getResource(); + + StringBuilder logMessage = new StringBuilder("Resource [") + .append(existingResource.toString()).append("] upgraded its "); + + if (resourceKey != null) { + existingResource.setResourceKey(resourceKey); + logMessage.append("resourceKey, "); + } + + if (name != null) { + existingResource.setName(name); + logMessage.append("name, "); + } + +// if (version != null) { +// existingResource.setVersion(version); +// } + + if (description != null) { + existingResource.setDescription(description); + logMessage.append("description, "); + } + +// if (pluginConfiguration != null) { +// existingResource.setPluginConfiguration(pluginConfiguration); +// } +// +// if (resourceConfiguration != null) { +// existingResource.setResourceConfiguration(resourceConfiguration); +// } + + logMessage.replace(logMessage.length() - 1, logMessage.length(), + "to become [").append(existingResource.toString()).append("]"); + + log.info(logMessage.toString()); + } else { + log.error("Upgraded a resource that is not present on the agent. This should not happen. The id of the missing resource is " + upgradeReport.getResourceId()); } - -// if (pluginConfiguration != null) { -// existingResource.setPluginConfiguration(pluginConfiguration); -// } -// -// if (resourceConfiguration != null) { -// existingResource.setResourceConfiguration(resourceConfiguration); -// } - } else { - log.error("Upgraded a resource that is not present on the agent. This should not happen. The id of the missing resource is " + upgradeReport.getResourceId()); } - } }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index 1101199..76d6265 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -465,65 +465,70 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot /** * @param existingResource * @param upgradeReport - * @return + * @return true if the resource was changed, false otherwise */ private boolean upgradeResource(Resource resource, ResourceUpgradeReport upgradeReport) { - boolean changed = false; if (resource != null) { String resourceKey = upgradeReport.getNewResourceKey(); String name = upgradeReport.getNewName(); - //String version = upgradeReport.getNewVersion(); +// String version = upgradeReport.getNewVersion(); String description = upgradeReport.getNewDescription(); // Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); // Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration();
- if (needsUpgrade(resource.getResourceKey(), resourceKey)) { - log.info("Resource [" + resource + "] upgraded its resource key from [" + - resource.getResourceKey() + "] to [" + resourceKey + "]"); - changed = true; - resource.setResourceKey(resourceKey); - } - - if (needsUpgrade(resource.getName(), name)) { - log.info("Resource [" + resource + "] upgraded its name from [" + - resource.getName() + "] to [" + name + "]"); - changed = true; - resource.setName(name); - } - -// if (version != null) { -// changed = updateResourceVersion(resource, version) || changed; -// } - - if (needsUpgrade(resource.getDescription(), description)) { - log.info("Resource [" + resource + "] upgraded its description from [" + - resource.getDescription() + "] to [" + description + "]"); - changed = true; - resource.setDescription(description); - } - -// if (pluginConfiguration != null) { -// if (!equalOrNull(pluginConfiguration, resource.getPluginConfiguration())) { -// log.info("Resource [" + resource + "] upgraded its plugin configuration from [" + -// resource.getPluginConfiguration() + "] to [" + pluginConfiguration + "]"); -// changed = true; -// resource.setPluginConfiguration(pluginConfiguration); + if (resourceKey != null || name != null || description != null) { + StringBuilder logMessage = new StringBuilder("Resource [") + .append(resource.toString()).append("] upgraded its "); + + if (needsUpgrade(resource.getResourceKey(), resourceKey)) { + resource.setResourceKey(resourceKey); + logMessage.append("resourceKey, "); + } + + if (needsUpgrade(resource.getName(), name)) { + resource.setName(name); + logMessage.append("name, "); + } + +// if (version != null) { +// changed = updateResourceVersion(resource, version) || changed; // } -// } -// -// if (resourceConfiguration != null) { -// if (!equalOrNull(resourceConfiguration, resource.getResourceConfiguration())) { -// //XXX Will this create a new history entry? -// -// log.info("Resource [" + resource + "] upgraded its resource configuration from [" + -// resource.getResourceConfiguration() + "] to [" + resourceConfiguration + "]"); -// -// changed = true; -// resource.setResourceConfiguration(resourceConfiguration); + + if (needsUpgrade(resource.getDescription(), description)) { + resource.setDescription(description); + logMessage.append("description, "); + } + +// if (pluginConfiguration != null) { +// if (!equalOrNull(pluginConfiguration, resource.getPluginConfiguration())) { +// log.info("Resource [" + resource + "] upgraded its plugin configuration from [" + +// resource.getPluginConfiguration() + "] to [" + pluginConfiguration + "]"); +// changed = true; +// resource.setPluginConfiguration(pluginConfiguration); +// } // } -// } +// +// if (resourceConfiguration != null) { +// if (!equalOrNull(resourceConfiguration, resource.getResourceConfiguration())) { +// //XXX Will this create a new history entry? +// +// log.info("Resource [" + resource + "] upgraded its resource configuration from [" + +// resource.getResourceConfiguration() + "] to [" + resourceConfiguration + "]"); +// +// changed = true; +// resource.setResourceConfiguration(resourceConfiguration); +// } +// } + + logMessage.replace(logMessage.length() - 1, logMessage.length(), + "to become [").append(resource.toString()).append("]"); + + log.info(logMessage.toString()); + + return true; + } } - return changed; + return false; }
private void validateInventoryReport(InventoryReport report) throws InvalidInventoryReportException { @@ -875,18 +880,6 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot updateInventoryStatus(subject, platforms, servers, target); }
- private static <T> boolean equalOrNull(T a, T b) { - if (a == null) { - return b == null; - } else { - if (b == null) { - return false; - } else { - return a.equals(b); - } - } - } - private static <T> boolean needsUpgrade(T oldValue, T newValue) { return newValue != null && (oldValue == null || !newValue.equals(oldValue)); }
commit d896c3792ebf8b45938972eb2ff2f45bd990be83 Author: Lukas Krejci lkrejci@redhat.com Date: Fri May 28 18:08:16 2010 +0200
Run a method in a new thread only if it originates in the interface that is being proxied.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/DiscoveryComponentProxyFactory.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/DiscoveryComponentProxyFactory.java index f8d1267..4c68970 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/DiscoveryComponentProxyFactory.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/DiscoveryComponentProxyFactory.java @@ -81,7 +81,7 @@ public class DiscoveryComponentProxyFactory {
// This is the handler that will actually invoke the method calls. ResourceDiscoveryComponentInvocationHandler handler = new ResourceDiscoveryComponentInvocationHandler(type, - component, timeout, pluginClassLoader); + component, timeout, pluginClassLoader, componentInterface);
// This is the proxy that will look like the discovery component object that the caller will use. T proxy = (T) Proxy.newProxyInstance(pluginClassLoader, new Class<?>[] { componentInterface }, handler); @@ -167,9 +167,10 @@ public class DiscoveryComponentProxyFactory { private final long timeout; private final ResourceType resourceType; private final ClassLoader pluginClassLoader; - + private Class<?> componentInterface; + public ResourceDiscoveryComponentInvocationHandler(ResourceType type, ResourceDiscoveryComponent component, - long timeout, ClassLoader pluginClassLoader) { + long timeout, ClassLoader pluginClassLoader, Class<?> componentInterface) { if (timeout <= 0) { throw new IllegalArgumentException("timeout value is not positive."); } @@ -181,6 +182,7 @@ public class DiscoveryComponentProxyFactory { this.component = component; this.timeout = timeout; this.pluginClassLoader = pluginClassLoader; + this.componentInterface = componentInterface; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { @@ -189,7 +191,7 @@ public class DiscoveryComponentProxyFactory { + "] has been blacklisted and can no longer be invoked."); }
- if (method.getDeclaringClass().getPackage().getName().startsWith("org.rhq")) { + if (componentInterface.isAssignableFrom(method.getDeclaringClass())) { return invokeInNewThread(method, args); } else { // toString(), etc.
commit 708dee442c2519ecc9d27c723e79239b14b25455 Author: Lukas Krejci lkrejci@redhat.com Date: Thu May 27 19:04:32 2010 +0200
Fixing a stupid bug that would cause no initial sync to happen during upgrade.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 83743d9..ba5f316 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -883,13 +883,22 @@ public class InventoryManager extends AgentService implements ContainerService, }
/** + * @see #handleReport(InventoryReport, boolean) + * @param report + * @return + */ + public boolean handleReport(InventoryReport report) { + return handleReport(report, false); + } + + /** * Send an inventory report to the Server. * * @param report the inventory report to be sent - * + * @param forceServerRoundtrip whether to report to the server even if there are no resources to report. * @return true if sending the report to the Server succeeded, or false otherwise */ - public boolean handleReport(InventoryReport report) { + public boolean handleReport(InventoryReport report, boolean forceServerRoundtrip) { if (!configuration.isInsideAgent()) { //TODO how does resource upgrade behave in the embedded scenario? return true; @@ -905,7 +914,7 @@ public class InventoryManager extends AgentService implements ContainerService, resourceUpgradeExecutor.sendRequests(); }
- if (report.getAddedRoots().isEmpty()) { + if (report.getAddedRoots().isEmpty() && !forceServerRoundtrip) { return true; // nothing to do }
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java index f0721cb..3397e76 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java @@ -130,7 +130,7 @@ public class ResourceUpgradeExecutor implements Runnable { //pull the inventory down from the server. //this will ensure that we have an up-to-date info on the //server inventory before we try to upgrade. - boolean syncResult = inventoryManager.handleReport(new InventoryReport(inventoryManager.getAgent())); + boolean syncResult = inventoryManager.handleReport(new InventoryReport(inventoryManager.getAgent()), true); if (!syncResult) { log.warn("Resource upgrade failed to sync up the inventory with the server."); return;
commit c9b82d93170e03e564ef2db2c50a007f4d1176dc Author: Lukas Krejci lkrejci@redhat.com Date: Thu May 27 18:39:32 2010 +0200
Make the ResourceUpgradeExecutor thread safe (even though it probably shouldn't have to be) and make sure it can only be run once.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java index 21da6bc..4d61e93 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java @@ -264,7 +264,7 @@ public class PluginContainer implements ContainerService {
//fire off the resource upgrade as soon as possible. It will run only once per plugin container //lifetime. - inventoryManager.executeResourceUpgradeImmediately(); + inventoryManager.fireResourceUpgrade();
return; } diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 7fcfd6e..83743d9 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -507,8 +507,13 @@ public class InventoryManager extends AgentService implements ContainerService, } }
- public void executeResourceUpgradeImmediately() { - resourceUpgradeExecutor.execute(); + /** + * Executes the resource upgrade asynchronously. + */ + public void fireResourceUpgrade() { + Thread resourceUpgradeThread = new Thread(resourceUpgradeExecutor, "Resource Upgrade Thread"); + resourceUpgradeThread.setDaemon(true); + resourceUpgradeThread.start(); }
public InventoryReport executeServerScanImmediately() { diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java index d15a1c2..f0721cb 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java @@ -27,9 +27,10 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.Queue; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -55,21 +56,22 @@ import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; * * @author Lukas Krejci */ -public class ResourceUpgradeExecutor { +public class ResourceUpgradeExecutor implements Runnable { private static final Log log = LogFactory.getLog(ResourceUpgradeExecutor.class);
/** * The upgrade runs only once in its lifetime. */ - private boolean enabled = true; - + private AtomicBoolean enabled = new AtomicBoolean(true); + private AtomicBoolean started = new AtomicBoolean(false); + private InventoryManager inventoryManager;
- private Set<ResourceUpgradeReport> reports; + private ConcurrentLinkedQueue<ResourceUpgradeReport> reports;
public ResourceUpgradeExecutor(InventoryManager inventoryManager) { this.inventoryManager = inventoryManager; - reports = new HashSet<ResourceUpgradeReport>(); + reports = new ConcurrentLinkedQueue<ResourceUpgradeReport>(); }
/** @@ -90,14 +92,14 @@ public class ResourceUpgradeExecutor { public <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> processAndQueue( ResourceUpgradeRequest<T> request, Set<Resource> discoveredResources) {
- return enabled ? executeResourceUpgradeAndStoreReport(request, discoveredResources) : null; + return enabled.get() ? executeResourceUpgradeAndStoreReport(request, discoveredResources) : null; }
/** * @return true if the executor is ready to perform the upgrade, false otherwise. */ public boolean isEnabled() { - return enabled; + return enabled.get(); }
/** @@ -105,9 +107,10 @@ public class ResourceUpgradeExecutor { * all the upgrade requests. */ public void sendRequests() { - if (enabled && reports.size() > 0) { - inventoryManager.mergeResourceFromUpgrade(reports); - reports.clear(); + if (enabled.get() && reports.size() > 0) { + HashSet<ResourceUpgradeReport> currentCopy = new HashSet<ResourceUpgradeReport>(reports); + inventoryManager.mergeResourceFromUpgrade(currentCopy); + reports.removeAll(currentCopy); } }
@@ -117,8 +120,8 @@ public class ResourceUpgradeExecutor { * After that a full discovery is performed and both the upgrade report and discovery report * are sent to the server. */ - public void execute() { - if (enabled) { + public void run() { + if (!started.getAndSet(true)) { if (log.isDebugEnabled()) { log.debug("Starting resource upgrade."); } @@ -140,7 +143,7 @@ public class ResourceUpgradeExecutor { log.warn("Resource upgrade failed.", t); } finally { //make sure to switch off the upgrade... - this.enabled = false; + this.enabled.set(false);
//clear up so that we don't hold unnecessary instances. reports.clear();
commit 760871c264eca5adf2cf322a48614b3cd68a3640 Author: Lukas Krejci lkrejci@redhat.com Date: Thu May 27 18:11:49 2010 +0200
Avoid deadlock by invoking the resource upgrade only after all services are initialized, removing the ability to perform plugin/resource configuration upgrades, generally made stuff work.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java index bfeba0d..979c456 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java @@ -44,9 +44,18 @@ public class ResourceUpgradeReport implements Serializable { private int resourceId; private String newResourceKey; private String newName; - private String newVersion; - private Configuration newPluginConfiguration; - private Configuration newResourceConfiguration; + +// version changes are handled differently. +// private String newVersion; + +// upgrading configurations would have large consequences. +// it would be difficult to synchronize the upgrade process +// with the agent or server initiated configuration updates. +// It could also be difficult for the UI to reflect more complicated +// structural changes as currently, it is assumed that +// the configurations are kept backwards compatible. +// private Configuration newPluginConfiguration; +// private Configuration newResourceConfiguration; private String newDescription;
public ResourceUpgradeReport() { @@ -85,29 +94,29 @@ public class ResourceUpgradeReport implements Serializable { this.newName = newName; }
- public String getNewVersion() { - return newVersion; - } - - public void setNewVersion(String newVersion) { - this.newVersion = newVersion; - } - - public Configuration getNewPluginConfiguration() { - return newPluginConfiguration; - } - - public void setNewPluginConfiguration(Configuration newPluginConfiguration) { - this.newPluginConfiguration = newPluginConfiguration; - } - - public Configuration getNewResourceConfiguration() { - return newResourceConfiguration; - } - - public void setNewResourceConfiguration(Configuration newResourceConfiguration) { - this.newResourceConfiguration = newResourceConfiguration; - } +// public String getNewVersion() { +// return newVersion; +// } +// +// public void setNewVersion(String newVersion) { +// this.newVersion = newVersion; +// } +// +// public Configuration getNewPluginConfiguration() { +// return newPluginConfiguration; +// } +// +// public void setNewPluginConfiguration(Configuration newPluginConfiguration) { +// this.newPluginConfiguration = newPluginConfiguration; +// } +// +// public Configuration getNewResourceConfiguration() { +// return newResourceConfiguration; +// } +// +// public void setNewResourceConfiguration(Configuration newResourceConfiguration) { +// this.newResourceConfiguration = newResourceConfiguration; +// }
public String getNewDescription() { return newDescription; diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java index 8970404..21da6bc 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java @@ -262,6 +262,10 @@ public class PluginContainer implements ContainerService { releaseLock(lock); }
+ //fire off the resource upgrade as soon as possible. It will run only once per plugin container + //lifetime. + inventoryManager.executeResourceUpgradeImmediately(); + return; }
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 044aa25..7fcfd6e 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -250,16 +250,7 @@ public class InventoryManager extends AgentService implements ContainerService, .getServiceDiscoveryInitialDelay(), configuration.getServiceDiscoveryPeriod(), TimeUnit.SECONDS); }
- //try to perform the full resource upgrade now. - //The initialization time is ideal for this because inventory manager - //is the first plugin container service to start and hence we can - //be sure that no under concurrent updates to the resources are happening. - //Because PC doesn't support online updates of plugins and needs to be restarted - //in order to pick up the changed plugins, we can be sure that running the - //upgrade only once at the PC start up is enough for the lifetime of - //plugin container (and hence this instance of InventoryManager). resourceUpgradeExecutor = new ResourceUpgradeExecutor(this); - resourceUpgradeExecutor.execute(); } finally { inventoryLock.writeLock().unlock(); } @@ -516,6 +507,10 @@ public class InventoryManager extends AgentService implements ContainerService, } }
+ public void executeResourceUpgradeImmediately() { + resourceUpgradeExecutor.execute(); + } + public InventoryReport executeServerScanImmediately() { try { return inventoryThreadPoolExecutor.submit((Callable<InventoryReport>) this.serverScanExecutor).get(); @@ -1180,10 +1175,10 @@ public class InventoryManager extends AgentService implements ContainerService, for (ResourceUpgradeReport upgradeReport : upgradeReports) { String resourceKey = upgradeReport.getNewResourceKey(); String name = upgradeReport.getNewName(); - String version = upgradeReport.getNewVersion(); + //String version = upgradeReport.getNewVersion(); String description = upgradeReport.getNewDescription(); - Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); - Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration(); + //Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); + //Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration();
ResourceContainer existingResourceContainer = getResourceContainer(upgradeReport.getResourceId()); if (existingResourceContainer != null) { @@ -1196,21 +1191,21 @@ public class InventoryManager extends AgentService implements ContainerService, existingResource.setName(name); }
- if (version != null) { - existingResource.setVersion(version); - } +// if (version != null) { +// existingResource.setVersion(version); +// }
if (description != null) { existingResource.setDescription(description); }
- if (pluginConfiguration != null) { - existingResource.setPluginConfiguration(pluginConfiguration); - } - - if (resourceConfiguration != null) { - existingResource.setResourceConfiguration(resourceConfiguration); - } +// if (pluginConfiguration != null) { +// existingResource.setPluginConfiguration(pluginConfiguration); +// } +// +// if (resourceConfiguration != null) { +// existingResource.setResourceConfiguration(resourceConfiguration); +// } } else { log.error("Upgraded a resource that is not present on the agent. This should not happen. The id of the missing resource is " + upgradeReport.getResourceId()); } diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java index b00dfd4..d15a1c2 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java @@ -69,6 +69,7 @@ public class ResourceUpgradeExecutor {
public ResourceUpgradeExecutor(InventoryManager inventoryManager) { this.inventoryManager = inventoryManager; + reports = new HashSet<ResourceUpgradeReport>(); }
/** @@ -104,8 +105,9 @@ public class ResourceUpgradeExecutor { * all the upgrade requests. */ public void sendRequests() { - if (enabled) { + if (enabled && reports.size() > 0) { inventoryManager.mergeResourceFromUpgrade(reports); + reports.clear(); } }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index 44f79a2..1101199 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -472,67 +472,56 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot if (resource != null) { String resourceKey = upgradeReport.getNewResourceKey(); String name = upgradeReport.getNewName(); - String version = upgradeReport.getNewVersion(); + //String version = upgradeReport.getNewVersion(); String description = upgradeReport.getNewDescription(); - Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); - Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration(); +// Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); +// Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration();
- if (resourceKey != null) { - if (!equalOrNull(resourceKey, resource.getResourceKey())) { - log.info("Resource [" + resource + "] upgraded its resource key from [" + - resource.getResourceKey() + "] to [" + resourceKey + "]"); - changed = true; - resource.setResourceKey(resourceKey); - } - } - - if (name != null) { - if (!equalOrNull(name, resource.getName())) { - log.info("Resource [" + resource + "] upgraded its name from [" + - resource.getName() + "] to [" + name + "]"); - changed = true; - resource.setName(name); - } - } - - if (version != null) { - changed = updateResourceVersion(resource, version) || changed; + if (needsUpgrade(resource.getResourceKey(), resourceKey)) { + log.info("Resource [" + resource + "] upgraded its resource key from [" + + resource.getResourceKey() + "] to [" + resourceKey + "]"); + changed = true; + resource.setResourceKey(resourceKey); }
- if (description != null) { - if (!equalOrNull(description, resource.getDescription())) { - log.info("Resource [" + resource + "] upgraded its description from [" + - resource.getDescription() + "] to [" + description + "]"); - changed = true; - resource.setDescription(description); - } + if (needsUpgrade(resource.getName(), name)) { + log.info("Resource [" + resource + "] upgraded its name from [" + + resource.getName() + "] to [" + name + "]"); + changed = true; + resource.setName(name); }
- if (pluginConfiguration != null) { - if (!equalOrNull(pluginConfiguration, resource.getPluginConfiguration())) { - log.info("Resource [" + resource + "] upgraded its plugin configuration from [" + - resource.getPluginConfiguration() + "] to [" + pluginConfiguration + "]"); - changed = true; - resource.setPluginConfiguration(pluginConfiguration); - } - } +// if (version != null) { +// changed = updateResourceVersion(resource, version) || changed; +// }
- if (resourceConfiguration != null) { - if (!equalOrNull(resourceConfiguration, resource.getResourceConfiguration())) { - //XXX Will this create a new history entry? - - log.info("Resource [" + resource + "] upgraded its resource configuration from [" + - resource.getResourceConfiguration() + "] to [" + resourceConfiguration + "]"); - - changed = true; - resource.setResourceConfiguration(resourceConfiguration); - } + if (needsUpgrade(resource.getDescription(), description)) { + log.info("Resource [" + resource + "] upgraded its description from [" + + resource.getDescription() + "] to [" + description + "]"); + changed = true; + resource.setDescription(description); }
- // If the resource was marked as deleted, reactivate it again. - if (resource.getInventoryStatus() == InventoryStatus.DELETED) { - resource.setInventoryStatus(InventoryStatus.COMMITTED); - } +// if (pluginConfiguration != null) { +// if (!equalOrNull(pluginConfiguration, resource.getPluginConfiguration())) { +// log.info("Resource [" + resource + "] upgraded its plugin configuration from [" + +// resource.getPluginConfiguration() + "] to [" + pluginConfiguration + "]"); +// changed = true; +// resource.setPluginConfiguration(pluginConfiguration); +// } +// } +// +// if (resourceConfiguration != null) { +// if (!equalOrNull(resourceConfiguration, resource.getResourceConfiguration())) { +// //XXX Will this create a new history entry? +// +// log.info("Resource [" + resource + "] upgraded its resource configuration from [" + +// resource.getResourceConfiguration() + "] to [" + resourceConfiguration + "]"); +// +// changed = true; +// resource.setResourceConfiguration(resourceConfiguration); +// } +// } } return changed; } @@ -897,4 +886,8 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot } } } + + private static <T> boolean needsUpgrade(T oldValue, T newValue) { + return newValue != null && (oldValue == null || !newValue.equals(oldValue)); + } } \ No newline at end of file
commit 1fe97fb0bb997c5e6c023adca8bb94da0fca7c79 Author: Lukas Krejci lkrejci@redhat.com Date: Thu May 27 16:18:21 2010 +0200
Actually call out back to inv manager to perform the upgrade.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java index f0f2b43..b00dfd4 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java @@ -105,7 +105,7 @@ public class ResourceUpgradeExecutor { */ public void sendRequests() { if (enabled) { - //TODO implement + inventoryManager.mergeResourceFromUpgrade(reports); } }
commit d0d2e582e00344b1720ee9d01a730fa1d1c3cb46 Author: Lukas Krejci lkrejci@redhat.com Date: Thu May 27 15:58:35 2010 +0200
reimplemented the upgrade process on the agent to happen only at init time. the server receives a full batch of upgrades, not one upgrade after another.
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java index cfa2459..61e5084 100644 --- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java @@ -138,13 +138,12 @@ public interface DiscoveryServerService { boolean updateResourceVersion(int resourceId, String version);
/** - * Upgrades the data of the resource according to the provided report. + * Upgrades the data of the resources according to the provided reports. * - * @param resourceId the id of the resource to be upgraded - * @param upgradeReport contains the information about the upgrade + * @param upgradeReports contains the information about the upgrade of individual resources. * @return true if the upgrade succeeded, false otherwise. */ - boolean upgradeResource(int resourceId, ResourceUpgradeReport upgradeReport); + boolean upgradeResources(Set<ResourceUpgradeReport> upgradeReports);
/** * Gives the server a chance to apply any necessary post-processing that's needed for newly committed resources diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java index 52acf09..bfeba0d 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java @@ -41,6 +41,7 @@ public class ResourceUpgradeReport implements Serializable {
private static final long serialVersionUID = 1L;
+ private int resourceId; private String newResourceKey; private String newName; private String newVersion; @@ -52,6 +53,22 @@ public class ResourceUpgradeReport implements Serializable {
}
+ /** + * The server-side id of the resource being upgraded. + * The discovery components don't need to assign this value. + */ + public int getResourceId() { + return resourceId; + } + + /** + * The server-side id of the resource being upgraded. + * The discovery components don't need to assign this value. + */ + public void setResourceId(int resourceId) { + this.resourceId = resourceId; + } + public String getNewResourceKey() { return newResourceKey; } diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 032256b..044aa25 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -33,9 +33,11 @@ import java.util.IdentityHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Queue; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -89,6 +91,8 @@ import org.rhq.core.pc.plugin.BlacklistedException; import org.rhq.core.pc.plugin.CanonicalResourceKey; import org.rhq.core.pc.plugin.PluginComponentFactory; import org.rhq.core.pc.plugin.PluginManager; +import org.rhq.core.pc.upgrade.ResourceUpgradeExecutor; +import org.rhq.core.pc.upgrade.ResourceUpgradeRequest; import org.rhq.core.pc.util.DiscoveryComponentProxyFactory; import org.rhq.core.pc.util.FacetLockType; import org.rhq.core.pc.util.LoggingThreadFactory; @@ -186,6 +190,11 @@ public class InventoryManager extends AgentService implements ContainerService, */ private AvailabilityCollectorThreadPool availabilityCollectors;
+ /** + * Handles the resource upgrade during the initialization of the inventory manager. + */ + private ResourceUpgradeExecutor resourceUpgradeExecutor; + public InventoryManager() { super(DiscoveryAgentService.class); } @@ -240,6 +249,17 @@ public class InventoryManager extends AgentService implements ContainerService, inventoryThreadPoolExecutor.scheduleWithFixedDelay(serviceScanExecutor, configuration .getServiceDiscoveryInitialDelay(), configuration.getServiceDiscoveryPeriod(), TimeUnit.SECONDS); } + + //try to perform the full resource upgrade now. + //The initialization time is ideal for this because inventory manager + //is the first plugin container service to start and hence we can + //be sure that no under concurrent updates to the resources are happening. + //Because PC doesn't support online updates of plugins and needs to be restarted + //in order to pick up the changed plugins, we can be sure that running the + //upgrade only once at the PC start up is enough for the lifetime of + //plugin container (and hence this instance of InventoryManager). + resourceUpgradeExecutor = new ResourceUpgradeExecutor(this); + resourceUpgradeExecutor.execute(); } finally { inventoryLock.writeLock().unlock(); } @@ -356,6 +376,23 @@ public class InventoryManager extends AgentService implements ContainerService, return results; }
+ public <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> invokeDiscoveryComponentResourceUpgradeFacet( + ResourceType resourceType, ResourceDiscoveryComponent<T> component, + Set<ResourceUpgradeContext<T>> inventoriedSiblings, ResourceUpgradeContext<?> parent, + Set<ResourceUpgradeContext<T>> discoveredResources) throws Throwable { + + long timeout = getDiscoveryComponentTimeout(resourceType); + try { + @SuppressWarnings("unchecked") + ResourceUpgradeFacet<T> proxy = this.discoveryComponentProxyFactory.getDiscoveryComponentProxy(resourceType, component, timeout, ResourceUpgradeFacet.class); + + return proxy.upgrade(inventoriedSiblings, parent, discoveredResources); + } catch (BlacklistedException e) { + log.debug(e); + return Collections.emptyMap(); + } + } + public DiscoveryComponentProxyFactory getDiscoveryComponentProxyFactory() { return this.discoveryComponentProxyFactory; } @@ -854,8 +891,20 @@ public class InventoryManager extends AgentService implements ContainerService, */ public boolean handleReport(InventoryReport report) { if (!configuration.isInsideAgent()) { + //TODO how does resource upgrade behave in the embedded scenario? return true; } + + //finish the resource upgrade. + //by now all the resource upgrade requests have been processed + //by the executor, which means that the inventory report + //we got already only contains the "correct" new resources and + //that the executor has all the upgrade requests queued up + //to be sent to the server in a batch. + if (resourceUpgradeExecutor.isEnabled()) { + resourceUpgradeExecutor.sendRequests(); + } + if (report.getAddedRoots().isEmpty()) { return true; // nothing to do } @@ -925,6 +974,7 @@ public class InventoryManager extends AgentService implements ContainerService, log.debug(String.format("DONE syncing local inventory [%d] ms.", (System.currentTimeMillis() - startTime))); } + // If we synced any Resources, one or more Resource components were probably started, // so run an avail check to report on their availabilities immediately. Also kick off // a service scan to scan those Resources for new child Resources. Kick both tasks off @@ -941,7 +991,7 @@ public class InventoryManager extends AgentService implements ContainerService, throw new RuntimeException(t); } } - + private void getAllUuids(ResourceSyncInfo syncInfo, Set<String> allServerSideUuids) { allServerSideUuids.add(syncInfo.getUuid()); for (ResourceSyncInfo child : syncInfo.getChildSyncInfos()) { @@ -1113,49 +1163,58 @@ public class InventoryManager extends AgentService implements ContainerService, return resourceContainer.updateAvailability(availabilityType); }
- private boolean mergeResourceFromUpgrade(Resource existingResource, ResourceUpgradeReport upgradeReport) { - String resourceKey = upgradeReport.getNewResourceKey(); - String name = upgradeReport.getNewName(); - String version = upgradeReport.getNewVersion(); - String description = upgradeReport.getNewDescription(); - Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); - Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration(); - + public boolean mergeResourceFromUpgrade(Set<ResourceUpgradeReport> upgradeReports) { boolean serverUpdated = false; try { ServerServices serverServices = this.configuration.getServerServices(); if (serverServices != null) { DiscoveryServerService discoveryServerService = serverServices.getDiscoveryServerService();
- serverUpdated = discoveryServerService.upgradeResource(existingResource.getId(), upgradeReport); + serverUpdated = discoveryServerService.upgradeResources(upgradeReports); } } catch (Exception e) { - log.error("Failed to upgrade the resource [" + existingResource + "] on the server.", e); + log.error("Failed to process resource upgrades on the server.", e); }
if (serverUpdated) { - if (resourceKey != null) { - existingResource.setResourceKey(resourceKey); - } - - if (name != null) { - existingResource.setName(name); - } - - if (version != null) { - existingResource.setVersion(version); - } - - if (description != null) { - existingResource.setDescription(description); - } - - if (pluginConfiguration != null) { - existingResource.setPluginConfiguration(pluginConfiguration); - } - - if (resourceConfiguration != null) { - existingResource.setResourceConfiguration(resourceConfiguration); + for (ResourceUpgradeReport upgradeReport : upgradeReports) { + String resourceKey = upgradeReport.getNewResourceKey(); + String name = upgradeReport.getNewName(); + String version = upgradeReport.getNewVersion(); + String description = upgradeReport.getNewDescription(); + Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); + Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration(); + + ResourceContainer existingResourceContainer = getResourceContainer(upgradeReport.getResourceId()); + if (existingResourceContainer != null) { + Resource existingResource = existingResourceContainer.getResource(); + if (resourceKey != null) { + existingResource.setResourceKey(resourceKey); + } + + if (name != null) { + existingResource.setName(name); + } + + if (version != null) { + existingResource.setVersion(version); + } + + if (description != null) { + existingResource.setDescription(description); + } + + if (pluginConfiguration != null) { + existingResource.setPluginConfiguration(pluginConfiguration); + } + + if (resourceConfiguration != null) { + existingResource.setResourceConfiguration(resourceConfiguration); + } + } else { + log.error("Upgraded a resource that is not present on the agent. This should not happen. The id of the missing resource is " + upgradeReport.getResourceId()); + } + } }
@@ -1453,6 +1512,23 @@ public class InventoryManager extends AgentService implements ContainerService, this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do }
+ public <T extends ResourceComponent> ResourceUpgradeContext<T> createResourceUpgradeContext(Resource resource, T parentComponent, ResourceDiscoveryComponent<T> discoveryComponent) { + File pluginDataDir = new File(this.configuration.getDataDirectory(), resource.getResourceType().getPlugin()); + + return new ResourceUpgradeContext<T>(resource, // the resource itself + parentComponent, // its parent component + discoveryComponent, // the discovery component (this is actually the proxy to it) + SystemInfoFactory.createSystemInfo(), // for native access + this.configuration.getTemporaryDirectory(), // location for plugin to write temp files + pluginDataDir, // location for plugin to write data files + this.configuration.getContainerName(), // the name of the agent/PC + getEventContext(resource), // for event access + getOperationContext(resource), // for operation manager access + getContentContext(resource), // for content manager access + this.availabilityCollectors, // for components that want to perform async avail checking + this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do + } + /** * This will send a resource error to the server (if applicable) to indicate that the given resource could not be * connected to due to an invalid plugin configuration. @@ -1536,7 +1612,7 @@ public class InventoryManager extends AgentService implements ContainerService, return getResourcesWithType(serverType, this.platform.getChildResources()); }
- private Set<Resource> getResourcesWithType(ResourceType serverType, Set<Resource> resources) { + public Set<Resource> getResourcesWithType(ResourceType serverType, Set<Resource> resources) { Set<Resource> servers = new HashSet<Resource>();
if (resources == null) { @@ -2061,76 +2137,10 @@ public class InventoryManager extends AgentService implements ContainerService, newResources.add(newResource); } } - - //check if the discovery component supports resource upgrade - //if it does, perform the resource upgrade straight away here during the discovery process. - if (discoveryComponent instanceof ResourceUpgradeFacet) { - ResourceUpgradeFacet resourceUpgrade = (ResourceUpgradeFacet) discoveryComponent; - - //the siblings are the resources of the type that is currently being discovered that are already - //present in the inventory. These are the candidate resources for the upgrade. - Set<Resource> siblings = getResourcesWithType(resourceType, parentResource.getChildResources()); - - ResourceUpgradeContext<?> parentUpgradeContext = null; - - //get the upgrade context of the parent resource so that it can be passed to the upgrade method - //of the discovery component. - if (parentResource != null) { - Resource grandParent = parentResource.getParentResource(); - ResourceContainer grandParentContainer = grandParent == null ? null : getResourceContainer(grandParent); - ResourceDiscoveryComponent parentDiscoveryComponent = PluginContainer.getInstance().getPluginComponentFactory() - .getDiscoveryComponent(parentResource.getResourceType(), grandParentContainer); - - parentUpgradeContext = new ResourceUpgradeContext(parentResource, parentDiscoveryComponent, parentResourceContext, availabilityCollectors); - } - - //convert the sibling resources into upgrade context objects so that the plugin methods don't access the - //domain objects directly. - Set<ResourceUpgradeContext> siblingContexts = new HashSet<ResourceUpgradeContext>(siblings.size()); - - //but we are going to need to update the resources in the end, so map the contexts with the resources. - Map<ResourceUpgradeContext, Resource> siblingContextToResource = new HashMap<ResourceUpgradeContext, Resource>(); - - for (Resource sibling : siblings) { - ResourceUpgradeContext siblingContext = new ResourceUpgradeContext(sibling, discoveryComponent, getResourceContainer(sibling).getResourceContext(), availabilityCollectors); - siblingContexts.add(siblingContext); - siblingContextToResource.put(siblingContext, sibling); - } - - //covert the new resources into contexts. - //map the resources by resource key so that we can later check for uniqueness of the reported results. - Set<ResourceUpgradeContext> newResourceContexts = new HashSet<ResourceUpgradeContext>(); - Map<String, Resource> newResourceKeyToResource = new HashMap<String, Resource>(); - - for (Resource newResource : newResources) { - ResourceUpgradeContext newUpgradeContext = new ResourceUpgradeContext(newResource, discoveryComponent, createResourceContext(newResource, parentComponent, discoveryComponent), availabilityCollectors); - newResourceContexts.add(newUpgradeContext); - newResourceKeyToResource.put(newResource.getResourceKey(), newResource); - } - - //ask the discovery component to upgrade the siblings. - Map<ResourceUpgradeContext, ResourceUpgradeReport> results = resourceUpgrade.upgrade(siblingContexts, parentUpgradeContext, newResourceContexts); - - //now go through the results and upgrade the resources as needed. - for(Map.Entry<ResourceUpgradeContext, ResourceUpgradeReport> upgradeEntry : results.entrySet()) { - Resource siblingToUpgrade = siblingContextToResource.get(upgradeEntry.getKey()); - ResourceUpgradeReport newData = upgradeEntry.getValue(); - - //upgrade the data on the server first - mergeResourceFromUpgrade(siblingToUpgrade, newData); - - //if there was a resource key upgrade, remove a resource with the same resource key - //from the discovery results. Otherwise we'd end up with 2 sibling resources with - //the same resource key, which is illegal. - if (newData.getNewResourceKey() != null) { - Resource newResourceToRemove = newResourceKeyToResource.get(newData.getNewResourceKey()); - if (newResourceToRemove != null) { - newResources.remove(newResourceToRemove); - } - } - } - }
+ if (resourceUpgradeExecutor.isEnabled()) { + resourceUpgradeExecutor.processAndQueue(new ResourceUpgradeRequest(newResources, context, parentResource.getId()), newResources); + } } catch (Throwable e) { // TODO GH: Add server/parent - up/down semantics so this won't happen just because a server is not up long elapsedTime = System.currentTimeMillis() - startTime; diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java new file mode 100644 index 0000000..f0f2b43 --- /dev/null +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeExecutor.java @@ -0,0 +1,285 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.pc.upgrade; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.rhq.core.clientapi.agent.PluginContainerException; +import org.rhq.core.clientapi.server.discovery.InventoryReport; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.domain.resource.ResourceUpgradeReport; +import org.rhq.core.pc.PluginContainer; +import org.rhq.core.pc.inventory.InventoryManager; +import org.rhq.core.pc.inventory.ResourceContainer; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceContext; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; + +/** + * This class is responsible for performing the resource upgrade on behalf on of {@link InventoryManager}. + * Despite its name, it is not an {@link java.util.concurrent.Executor} implementation. + * + * @author Lukas Krejci + */ +public class ResourceUpgradeExecutor { + private static final Log log = LogFactory.getLog(ResourceUpgradeExecutor.class); + + /** + * The upgrade runs only once in its lifetime. + */ + private boolean enabled = true; + + private InventoryManager inventoryManager; + + private Set<ResourceUpgradeReport> reports; + + public ResourceUpgradeExecutor(InventoryManager inventoryManager) { + this.inventoryManager = inventoryManager; + } + + /** + * This method is called from within the {@link InventoryManager} during the + * discovery process as individual upgrade requests are generated. + * <p> + * This method calls the appropriate discovery component to perform the upgrade and + * at the same time stores off the results so that they can be sent to the server + * at the end of the discovery in one big batch. + * <p> + * The provided set of discovery results is updated if this method detects that an existing + * resource upgrade would result in a resource key collision with some of the newly discovered + * resources. + * + * @param request the upgrade request + * @param discoveredResources the set of discovered resources that this method can optionally remove some elements from. + */ + public <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> processAndQueue( + ResourceUpgradeRequest<T> request, Set<Resource> discoveredResources) { + + return enabled ? executeResourceUpgradeAndStoreReport(request, discoveredResources) : null; + } + + /** + * @return true if the executor is ready to perform the upgrade, false otherwise. + */ + public boolean isEnabled() { + return enabled; + } + + /** + * This method is called from within the {@link InventoryManager} once it's collected + * all the upgrade requests. + */ + public void sendRequests() { + if (enabled) { + //TODO implement + } + } + + /** + * Performs the resource upgrade. First, a full inventory report is pulled down from the + * server to ensure we have an up-to-date picture of the inventory. + * After that a full discovery is performed and both the upgrade report and discovery report + * are sent to the server. + */ + public void execute() { + if (enabled) { + if (log.isDebugEnabled()) { + log.debug("Starting resource upgrade."); + } + + try { + //pull the inventory down from the server. + //this will ensure that we have an up-to-date info on the + //server inventory before we try to upgrade. + boolean syncResult = inventoryManager.handleReport(new InventoryReport(inventoryManager.getAgent())); + if (!syncResult) { + log.warn("Resource upgrade failed to sync up the inventory with the server."); + return; + } + + //fire off the full discovery + inventoryManager.executeServerScanImmediately(); + inventoryManager.executeServiceScanImmediately(); + } catch (Throwable t) { + log.warn("Resource upgrade failed.", t); + } finally { + //make sure to switch off the upgrade... + this.enabled = false; + + //clear up so that we don't hold unnecessary instances. + reports.clear(); + + if (log.isDebugEnabled()) { + log.debug("Resource upgrade finished."); + } + } + + } else { + if (log.isDebugEnabled()) { + log.debug("ResourceUpgradeExecutor already ran before. Skipping the execution."); + } + } + } + + /** + * Executes the resource upgrade request on the agent (if the appropriate discovery component support {@link ResourceUpgradeFacet}). + * + * @param request the upgrade request to execute on the agent. + * @param discoveredResources the set of the discovered resources that this method can remove some elements from + * @return the resulting upgrade map as reported by the plugin from {@link ResourceUpgradeFacet#upgrade(Set, ResourceUpgradeContext, Set)} method. + * + * @throws PluginContainerException + */ + private <T extends ResourceComponent> Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> executeResourceUpgradeAndStoreReport( + ResourceUpgradeRequest<T> request, Set<Resource> discoveredResources) { + + ResourceDiscoveryContext<T> discoveryContext = request.getDiscoveryContext(); + Set<Resource> newResources = request.getDiscoveredResources(); + Integer parentResourceId = request.getParentResourceId(); + + try { + ResourceType resourceType = discoveryContext.getResourceType(); + ResourceContainer parentResourceContainer = null; + Resource parentResource = null; + if (parentResourceId != null) { + parentResourceContainer = inventoryManager.getResourceContainer(parentResourceId); + if (parentResourceContainer != null) { + parentResource = parentResourceContainer.getResource(); + } + } + + @SuppressWarnings("unchecked") + ResourceDiscoveryComponent<T> discoveryComponent = PluginContainer.getInstance() + .getPluginComponentFactory().getDiscoveryComponent(resourceType, parentResourceContainer); + + ResourceContext<?> parentResourceContext = discoveryContext.getParentResourceContext(); + + T parentComponent = discoveryContext.getParentResourceComponent(); + + //check if the discovery component supports resource upgrade + //if it does, perform the resource upgrade straight away here during the discovery process. + if (discoveryComponent instanceof ResourceUpgradeFacet) { + //the siblings are the resources of the type that is currently being discovered that are already + //present in the inventory. These are the candidate resources for the upgrade. + Set<Resource> siblings = parentResource == null ? Collections.singleton(inventoryManager.getPlatform()) + : inventoryManager.getResourcesWithType(resourceType, parentResource.getChildResources()); + + //get the upgrade context of the parent resource so that it can be passed to the upgrade method + //of the discovery component. + ResourceUpgradeContext<?> parentUpgradeContext = null; + + if (parentResource != null) { + Resource grandParent = parentResource.getParentResource(); + ResourceContainer grandParentContainer = grandParent == null ? null : inventoryManager + .getResourceContainer(grandParent); + + @SuppressWarnings("unchecked") + ResourceDiscoveryComponent<ResourceComponent> parentDiscoveryComponent = PluginContainer + .getInstance().getPluginComponentFactory().getDiscoveryComponent( + parentResource.getResourceType(), grandParentContainer); + + ResourceComponent<?> grandParentResourceComponent = grandParentContainer == null ? null + : grandParentContainer.getResourceComponent(); + + parentUpgradeContext = inventoryManager.createResourceUpgradeContext(parentResource, + grandParentResourceComponent, parentDiscoveryComponent); + } + + //convert the sibling resources into upgrade context objects so that the plugin methods don't access the + //domain objects directly. + Set<ResourceUpgradeContext<T>> siblingContexts = new HashSet<ResourceUpgradeContext<T>>(siblings.size()); + + //but we are going to need to update the resources in the end, so map the contexts with the resources. + Map<ResourceUpgradeContext<T>, Resource> siblingContextToResource = new HashMap<ResourceUpgradeContext<T>, Resource>(); + + for (Resource sibling : siblings) { + ResourceUpgradeContext<T> siblingContext = inventoryManager.createResourceUpgradeContext(sibling, + parentComponent, discoveryComponent); + siblingContexts.add(siblingContext); + siblingContextToResource.put(siblingContext, sibling); + } + + //convert the new resources into contexts. + //map the resources by resource key so that we can later check for uniqueness of the reported results. + Set<ResourceUpgradeContext<T>> newResourceContexts = new HashSet<ResourceUpgradeContext<T>>(); + Map<String, Resource> newResourceKeyToResource = new HashMap<String, Resource>(); + + for (Resource newResource : newResources) { + ResourceUpgradeContext<T> newUpgradeContext = inventoryManager.createResourceUpgradeContext( + newResource, parentComponent, discoveryComponent); + newResourceContexts.add(newUpgradeContext); + newResourceKeyToResource.put(newResource.getResourceKey(), newResource); + } + + //ask the discovery component to upgrade the siblings. + Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> results; + try { + results = inventoryManager.invokeDiscoveryComponentResourceUpgradeFacet(resourceType, + discoveryComponent, siblingContexts, parentUpgradeContext, newResourceContexts); + + //now go through the results and upgrade the resources as needed. + for (Map.Entry<ResourceUpgradeContext<T>, ResourceUpgradeReport> upgradeEntry : results.entrySet()) { + Resource siblingToUpgrade = siblingContextToResource.get(upgradeEntry.getKey()); + ResourceUpgradeReport newData = upgradeEntry.getValue(); + + //upgrade the data on the server first + newData.setResourceId(siblingToUpgrade.getId()); + reports.add(newData); + + //if there was a resource key upgrade, remove a resource with the same resource key + //from the discovery results. Otherwise we'd end up with 2 sibling resources with + //the same resource key, which is illegal. + if (newData.getNewResourceKey() != null) { + Resource newResourceToRemove = newResourceKeyToResource.get(newData.getNewResourceKey()); + if (newResourceToRemove != null) { + discoveredResources.remove(newResourceToRemove); + } + } + } + + return results; + } catch (Throwable t) { + log.warn("Exception in discovery component " + discoveryComponent.getClass() + " upgrade method.", + t); + } + } + } catch (PluginContainerException e) { + log.warn("Failed resource upgrade of children of resource id " + parentResourceId, e); + } + return null; + } +} diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeRequest.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeRequest.java new file mode 100644 index 0000000..25178ee --- /dev/null +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/upgrade/ResourceUpgradeRequest.java @@ -0,0 +1,35 @@ +package org.rhq.core.pc.upgrade; + +import java.util.Set; + +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; + +/** + * This class is used to store the requests for resource upgrade that originate in + * the discovery workflow, but can only be executed after an inventory sync. + */ +public class ResourceUpgradeRequest<T extends ResourceComponent> { + private Set<Resource> discoveredResources; + private ResourceDiscoveryContext<T> discoveryContext; + private Integer parentResourceId; + + public ResourceUpgradeRequest(Set<Resource> discoveredResources, ResourceDiscoveryContext<T> discoveryContext, Integer parentResourceId) { + this.discoveredResources = discoveredResources; + this.discoveryContext = discoveryContext; + this.parentResourceId = parentResourceId; + } + + public Set<Resource> getDiscoveredResources() { + return discoveredResources; + } + + public ResourceDiscoveryContext<T> getDiscoveryContext() { + return discoveryContext; + } + + public Integer getParentResourceId() { + return parentResourceId; + } +} \ No newline at end of file diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/DiscoveryComponentProxyFactory.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/DiscoveryComponentProxyFactory.java index 57b9874..f8d1267 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/DiscoveryComponentProxyFactory.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/DiscoveryComponentProxyFactory.java @@ -189,7 +189,7 @@ public class DiscoveryComponentProxyFactory { + "] has been blacklisted and can no longer be invoked."); }
- if (method.getDeclaringClass().equals(ResourceDiscoveryComponent.class)) { + if (method.getDeclaringClass().getPackage().getName().startsWith("org.rhq")) { return invokeInNewThread(method, args); } else { // toString(), etc. diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index 2d3e9e6..44f79a2 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -401,17 +401,20 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot } }
- public boolean upgradeResource(int resourceId, ResourceUpgradeReport upgradeReport) { - Resource existingResource = this.entityManager.find(Resource.class, resourceId); - if (existingResource != null) { - boolean changed = upgradeResource(existingResource, upgradeReport); - if (changed) { - this.entityManager.merge(existingResource); + public boolean upgradeResources(Set<ResourceUpgradeReport> upgradeReports) { + for (ResourceUpgradeReport report : upgradeReports) { + Resource existingResource = this.entityManager.find(Resource.class, report.getResourceId()); + if (existingResource != null) { + boolean changed = upgradeResource(existingResource, report); + if (changed) { + this.entityManager.merge(existingResource); + } + } else { + this.entityManager.getTransaction().setRollbackOnly(); + return false; } - return true; - } else { - return false; } + return true; }
/** diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java index 4e60ffb..af518eb 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java @@ -21,6 +21,7 @@ package org.rhq.enterprise.server.discovery; import java.util.EnumSet; import java.util.List; import java.util.Map; +import java.util.Set;
import javax.ejb.Local;
@@ -179,11 +180,10 @@ public interface DiscoveryBossLocal extends DiscoveryBossRemote { boolean updateResourceVersion(int resourceId, String version);
/** - * Upgrades the data of the resource according to the provided report. + * Upgrades the data of the resources according to the provided reports. * - * @param resourceId the id of the resource to be upgraded - * @param upgradeReport contains the information about the upgrade + * @param upgradeReports contains the information about the upgrade of individual resources. * @return true if the upgrade succeeded, false otherwise. */ - boolean upgradeResource(int resourceId, ResourceUpgradeReport upgradeReport); + boolean upgradeResources(Set<ResourceUpgradeReport> upgradeReports); } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java index 720465e..0f90cdc 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java @@ -177,9 +177,9 @@ public class DiscoveryServerServiceImpl implements DiscoveryServerService { return discoveryBoss.updateResourceVersion(resourceId, version); }
- public boolean upgradeResource(int resourceId, ResourceUpgradeReport upgradeReport) { + public boolean upgradeResources(Set<ResourceUpgradeReport> upgradeReports) { DiscoveryBossLocal discoveryBoss = LookupUtil.getDiscoveryBoss(); - return discoveryBoss.upgradeResource(resourceId, upgradeReport); + return discoveryBoss.upgradeResources(upgradeReports); }
private static Resource convertToPojoResource(Resource resource, boolean includeDescendants) { diff --git a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java index fc001f9..2f3431b 100644 --- a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java +++ b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java @@ -170,10 +170,10 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen return discoveredResources; }
- public Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSiblings, - ResourceUpgradeContext<PlatformComponent> parentContext, Set<ResourceUpgradeContext> discoveryResults) { + public Map<ResourceUpgradeContext<PlatformComponent>, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext<PlatformComponent>> inventoriedSiblings, + ResourceUpgradeContext<?> parentContext, Set<ResourceUpgradeContext<PlatformComponent>> discoveryResults) {
- Map<ResourceUpgradeContext, ResourceUpgradeReport> ret = new HashMap<ResourceUpgradeContext, ResourceUpgradeReport>(); + Map<ResourceUpgradeContext<PlatformComponent>, ResourceUpgradeReport> ret = new HashMap<ResourceUpgradeContext<PlatformComponent>, ResourceUpgradeReport>();
for (ResourceUpgradeContext context : inventoriedSiblings) { String inventoriedResourceKey = context.getResourceKey();
commit 15ee2d7c543480cb636eb0b2c68a773d0728fe78 Author: Lukas Krejci lkrejci@redhat.com Date: Thu May 27 12:11:54 2010 +0200
Small interface correction.
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java index cea777a..914641c 100644 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java @@ -37,7 +37,6 @@ import org.rhq.core.pluginapi.inventory.ResourceComponent; * * @author Lukas Krejci */ -@SuppressWarnings("unchecked") public interface ResourceUpgradeFacet<T extends ResourceComponent> {
/** @@ -54,5 +53,5 @@ public interface ResourceUpgradeFacet<T extends ResourceComponent> { * inventoriedSiblings set, the values are the upgrade reports detailing what the data of the * corresponding siblings should be upgraded to. */ - Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSiblings, ResourceUpgradeContext<T> parentContext, Set<ResourceUpgradeContext> discoveryResults); + Map<ResourceUpgradeContext<T>, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext<T>> inventoriedSiblings, ResourceUpgradeContext<? extends ResourceComponent> parentContext, Set<ResourceUpgradeContext<T>> discoveryResults); }
commit df9228b55e6fdd293be1b1b030a00fb109fd649c Author: Lukas Krejci lkrejci@redhat.com Date: Wed May 26 15:06:37 2010 +0200
added some comments, fixed typos and one possible NPE.
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java index b68b5df..cea777a 100644 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java @@ -45,7 +45,7 @@ public interface ResourceUpgradeFacet<T extends ResourceComponent> { * The exact same discovery results are passed to this method along with the set of resources * that already exist in the inventory. * - * @param inventoriedSimblings the existing resources + * @param inventoriedSiblings the existing resources * @param parentContext the parent of both the newly discovered and existing resources * @param discoveryResults the discovered resources. The resources from this set that have * the same resource key as one of the inventoried siblings (after upgrade using the results of this method) won't @@ -54,5 +54,5 @@ public interface ResourceUpgradeFacet<T extends ResourceComponent> { * inventoriedSiblings set, the values are the upgrade reports detailing what the data of the * corresponding siblings should be upgraded to. */ - Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSimblings, ResourceUpgradeContext<T> parentContext, Set<ResourceUpgradeContext> discoveryResults); + Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSiblings, ResourceUpgradeContext<T> parentContext, Set<ResourceUpgradeContext> discoveryResults); } diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 866fd79..032256b 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -2062,21 +2062,33 @@ public class InventoryManager extends AgentService implements ContainerService, } }
- //check for upgrade support + //check if the discovery component supports resource upgrade + //if it does, perform the resource upgrade straight away here during the discovery process. if (discoveryComponent instanceof ResourceUpgradeFacet) { ResourceUpgradeFacet resourceUpgrade = (ResourceUpgradeFacet) discoveryComponent;
+ //the siblings are the resources of the type that is currently being discovered that are already + //present in the inventory. These are the candidate resources for the upgrade. Set<Resource> siblings = getResourcesWithType(resourceType, parentResource.getChildResources());
- Resource grandParent = parentResource.getParentResource(); - ResourceContainer grandParentContainer = grandParent == null ? null : getResourceContainer(grandParent); - ResourceDiscoveryComponent parentDiscoveryComponent = PluginContainer.getInstance().getPluginComponentFactory() - .getDiscoveryComponent(parentResource.getResourceType(), grandParentContainer); - - ResourceUpgradeContext<?> parentUpgradeContext = new ResourceUpgradeContext(parentResource, parentDiscoveryComponent, parentResourceContext, availabilityCollectors); + ResourceUpgradeContext<?> parentUpgradeContext = null; + + //get the upgrade context of the parent resource so that it can be passed to the upgrade method + //of the discovery component. + if (parentResource != null) { + Resource grandParent = parentResource.getParentResource(); + ResourceContainer grandParentContainer = grandParent == null ? null : getResourceContainer(grandParent); + ResourceDiscoveryComponent parentDiscoveryComponent = PluginContainer.getInstance().getPluginComponentFactory() + .getDiscoveryComponent(parentResource.getResourceType(), grandParentContainer); + + parentUpgradeContext = new ResourceUpgradeContext(parentResource, parentDiscoveryComponent, parentResourceContext, availabilityCollectors); + }
+ //convert the sibling resources into upgrade context objects so that the plugin methods don't access the + //domain objects directly. Set<ResourceUpgradeContext> siblingContexts = new HashSet<ResourceUpgradeContext>(siblings.size());
+ //but we are going to need to update the resources in the end, so map the contexts with the resources. Map<ResourceUpgradeContext, Resource> siblingContextToResource = new HashMap<ResourceUpgradeContext, Resource>();
for (Resource sibling : siblings) { @@ -2085,6 +2097,8 @@ public class InventoryManager extends AgentService implements ContainerService, siblingContextToResource.put(siblingContext, sibling); }
+ //covert the new resources into contexts. + //map the resources by resource key so that we can later check for uniqueness of the reported results. Set<ResourceUpgradeContext> newResourceContexts = new HashSet<ResourceUpgradeContext>(); Map<String, Resource> newResourceKeyToResource = new HashMap<String, Resource>();
@@ -2094,12 +2108,15 @@ public class InventoryManager extends AgentService implements ContainerService, newResourceKeyToResource.put(newResource.getResourceKey(), newResource); }
+ //ask the discovery component to upgrade the siblings. Map<ResourceUpgradeContext, ResourceUpgradeReport> results = resourceUpgrade.upgrade(siblingContexts, parentUpgradeContext, newResourceContexts);
+ //now go through the results and upgrade the resources as needed. for(Map.Entry<ResourceUpgradeContext, ResourceUpgradeReport> upgradeEntry : results.entrySet()) { Resource siblingToUpgrade = siblingContextToResource.get(upgradeEntry.getKey()); ResourceUpgradeReport newData = upgradeEntry.getValue();
+ //upgrade the data on the server first mergeResourceFromUpgrade(siblingToUpgrade, newData);
//if there was a resource key upgrade, remove a resource with the same resource key diff --git a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java index 45887f6..fc001f9 100644 --- a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java +++ b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java @@ -170,12 +170,12 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen return discoveredResources; }
- public Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSimblings, + public Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSiblings, ResourceUpgradeContext<PlatformComponent> parentContext, Set<ResourceUpgradeContext> discoveryResults) {
Map<ResourceUpgradeContext, ResourceUpgradeReport> ret = new HashMap<ResourceUpgradeContext, ResourceUpgradeReport>();
- for (ResourceUpgradeContext context : inventoriedSimblings) { + for (ResourceUpgradeContext context : inventoriedSiblings) { String inventoriedResourceKey = context.getResourceKey(); File inventoriedResourceKeyAsPath = new File(inventoriedResourceKey);
commit 3c7d8241ea85fdceb317049664886b204f4d9cba Author: Lukas Krejci lkrejci@redhat.com Date: Wed May 26 14:49:03 2010 +0200
renamed the org.rhq.core.pluginapi.migration package to org.rhq.core.pluginapi.upgrade to make it use the "upgrade" notion used by the classes in it.
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeContext.java deleted file mode 100644 index e8c5f03..0000000 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeContext.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2010 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, version 2, as - * published by the Free Software Foundation, and/or the GNU Lesser - * General Public License, version 2.1, also as published by the Free - * Software Foundation. - * - * 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 and the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * and the GNU Lesser 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.core.pluginapi.migration; - -import java.io.File; -import java.util.concurrent.Executor; - -import org.rhq.core.domain.configuration.Configuration; -import org.rhq.core.domain.resource.Resource; -import org.rhq.core.pluginapi.content.ContentContext; -import org.rhq.core.pluginapi.event.EventContext; -import org.rhq.core.pluginapi.inventory.PluginContainerDeployment; -import org.rhq.core.pluginapi.inventory.ResourceComponent; -import org.rhq.core.pluginapi.inventory.ResourceContext; -import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; -import org.rhq.core.pluginapi.operation.OperationContext; -import org.rhq.core.system.SystemInfo; - -/** - * Represents a resource during the resource upgrade phase of discovery. - * - * @see ResourceUpgradeFacet - * - * @author Lukas Krejci - */ -@SuppressWarnings("unchecked") -public class ResourceUpgradeContext<T extends ResourceComponent> extends ResourceContext<T> { - - private final Configuration resourceConfiguration; - private final String name; - private final String description; - - /** - * @see ResourceContext#ResourceContext(Resource, ResourceComponent, ResourceDiscoveryComponent, SystemInfo, File, File, String, EventContext, OperationContext, ContentContext, Executor, PluginContainerDeployment) - */ - public ResourceUpgradeContext(Resource resource, T parentResourceComponent, - ResourceDiscoveryComponent resourceDiscoveryComponent, SystemInfo systemInfo, File temporaryDirectory, - File dataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext, - ContentContext contentContext, Executor availCollectorThreadPool, - PluginContainerDeployment pluginContainerDeployment) { - - super(resource, parentResourceComponent, resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, - pluginContainerName, eventContext, operationContext, contentContext, availCollectorThreadPool, - pluginContainerDeployment); - - this.resourceConfiguration = resource.getResourceConfiguration(); - this.name = resource.getName(); - this.description = resource.getDescription(); - } - - public ResourceUpgradeContext(Resource resource, ResourceDiscoveryComponent discoveryComponent, ResourceContext<T> context, Executor availCollectorThreadPool) { - this(resource, context.getParentResourceComponent(), discoveryComponent, context.getSystemInformation(), context.getTemporaryDirectory(), - context.getDataDirectory(), context.getPluginContainerName(), context.getEventContext(), context.getOperationContext(), - context.getContentContext(), availCollectorThreadPool, context.getPluginContainerDeployment()); - } - - public Configuration getResourceConfiguration() { - return resourceConfiguration; - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } -} diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeFacet.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeFacet.java deleted file mode 100644 index df372bf..0000000 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeFacet.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2010 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, version 2, as - * published by the Free Software Foundation, and/or the GNU Lesser - * General Public License, version 2.1, also as published by the Free - * Software Foundation. - * - * 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 and the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * and the GNU Lesser 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.core.pluginapi.migration; - -import java.util.Map; -import java.util.Set; - -import org.rhq.core.domain.resource.ResourceUpgradeReport; -import org.rhq.core.pluginapi.inventory.ResourceComponent; - -/** - * This interface is to be implemented by discovery classes if they want to support - * upgrading the existing resources to a new format needed by an updated resource component. - * This is useful for example in the case when a new version of plugin redefined a resource - * key generation algorithm and wants to upgrade the legacy resources to use the new format. - * - * @author Lukas Krejci - */ -@SuppressWarnings("unchecked") -public interface ResourceUpgradeFacet<T extends ResourceComponent> { - - /** - * This method is called on the discovery component straight after it has finished the discovery. - * The exact same discovery results are passed to this method along with the set of resources - * that already exist in the inventory. - * - * @param inventoriedSimblings the existing resources - * @param parentContext the parent of both the newly discovered and existing resources - * @param discoveryResults the discovered resources. The resources from this set that have - * the same resource key as one of the inventoried siblings (after upgrade using the results of this method) won't - * be reported. - * @return the mapping of old resources to the newly desired data. The keys are instances from the - * inventoriedSiblings set, the values are the upgrade reports detailing what the data of the - * corresponding siblings should be upgraded to. - */ - Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSimblings, ResourceUpgradeContext<T> parentContext, Set<ResourceUpgradeContext> discoveryResults); -} diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java new file mode 100644 index 0000000..35f5029 --- /dev/null +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeContext.java @@ -0,0 +1,89 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.pluginapi.upgrade; + +import java.io.File; +import java.util.concurrent.Executor; + +import org.rhq.core.domain.configuration.Configuration; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.pluginapi.content.ContentContext; +import org.rhq.core.pluginapi.event.EventContext; +import org.rhq.core.pluginapi.inventory.PluginContainerDeployment; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceContext; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.operation.OperationContext; +import org.rhq.core.system.SystemInfo; + +/** + * Represents a resource during the resource upgrade phase of discovery. + * + * @see ResourceUpgradeFacet + * + * @author Lukas Krejci + */ +@SuppressWarnings("unchecked") +public class ResourceUpgradeContext<T extends ResourceComponent> extends ResourceContext<T> { + + private final Configuration resourceConfiguration; + private final String name; + private final String description; + + /** + * @see ResourceContext#ResourceContext(Resource, ResourceComponent, ResourceDiscoveryComponent, SystemInfo, File, File, String, EventContext, OperationContext, ContentContext, Executor, PluginContainerDeployment) + */ + public ResourceUpgradeContext(Resource resource, T parentResourceComponent, + ResourceDiscoveryComponent resourceDiscoveryComponent, SystemInfo systemInfo, File temporaryDirectory, + File dataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext, + ContentContext contentContext, Executor availCollectorThreadPool, + PluginContainerDeployment pluginContainerDeployment) { + + super(resource, parentResourceComponent, resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, + pluginContainerName, eventContext, operationContext, contentContext, availCollectorThreadPool, + pluginContainerDeployment); + + this.resourceConfiguration = resource.getResourceConfiguration(); + this.name = resource.getName(); + this.description = resource.getDescription(); + } + + public ResourceUpgradeContext(Resource resource, ResourceDiscoveryComponent discoveryComponent, ResourceContext<T> context, Executor availCollectorThreadPool) { + this(resource, context.getParentResourceComponent(), discoveryComponent, context.getSystemInformation(), context.getTemporaryDirectory(), + context.getDataDirectory(), context.getPluginContainerName(), context.getEventContext(), context.getOperationContext(), + context.getContentContext(), availCollectorThreadPool, context.getPluginContainerDeployment()); + } + + public Configuration getResourceConfiguration() { + return resourceConfiguration; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } +} diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java new file mode 100644 index 0000000..b68b5df --- /dev/null +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/upgrade/ResourceUpgradeFacet.java @@ -0,0 +1,58 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.pluginapi.upgrade; + +import java.util.Map; +import java.util.Set; + +import org.rhq.core.domain.resource.ResourceUpgradeReport; +import org.rhq.core.pluginapi.inventory.ResourceComponent; + +/** + * This interface is to be implemented by discovery classes if they want to support + * upgrading the existing resources to a new format needed by an updated resource component. + * This is useful for example in the case when a new version of plugin redefined a resource + * key generation algorithm and wants to upgrade the legacy resources to use the new format. + * + * @author Lukas Krejci + */ +@SuppressWarnings("unchecked") +public interface ResourceUpgradeFacet<T extends ResourceComponent> { + + /** + * This method is called on the discovery component straight after it has finished the discovery. + * The exact same discovery results are passed to this method along with the set of resources + * that already exist in the inventory. + * + * @param inventoriedSimblings the existing resources + * @param parentContext the parent of both the newly discovered and existing resources + * @param discoveryResults the discovered resources. The resources from this set that have + * the same resource key as one of the inventoried siblings (after upgrade using the results of this method) won't + * be reported. + * @return the mapping of old resources to the newly desired data. The keys are instances from the + * inventoriedSiblings set, the values are the upgrade reports detailing what the data of the + * corresponding siblings should be upgraded to. + */ + Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSimblings, ResourceUpgradeContext<T> parentContext, Set<ResourceUpgradeContext> discoveryResults); +} diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index feb2d81..866fd79 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -105,10 +105,10 @@ import org.rhq.core.pluginapi.inventory.ResourceComponent; import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; -import org.rhq.core.pluginapi.migration.ResourceUpgradeContext; -import org.rhq.core.pluginapi.migration.ResourceUpgradeFacet; import org.rhq.core.pluginapi.operation.OperationContext; import org.rhq.core.pluginapi.operation.OperationServices; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; import org.rhq.core.system.SystemInfo; import org.rhq.core.system.SystemInfoFactory; import org.rhq.core.util.exception.ThrowableUtil; diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/RuntimeDiscoveryExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/RuntimeDiscoveryExecutor.java index c60d4a8..e31ffda 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/RuntimeDiscoveryExecutor.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/RuntimeDiscoveryExecutor.java @@ -46,8 +46,8 @@ import org.rhq.core.pc.plugin.PluginComponentFactory; import org.rhq.core.pluginapi.inventory.ProcessScanResult; import org.rhq.core.pluginapi.inventory.ResourceComponent; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; -import org.rhq.core.pluginapi.migration.ResourceUpgradeContext; -import org.rhq.core.pluginapi.migration.ResourceUpgradeFacet; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; import org.rhq.core.util.exception.ExceptionPackage; import org.rhq.core.util.exception.Severity;
diff --git a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java index 4d80ac1..45887f6 100644 --- a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java +++ b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java @@ -46,8 +46,8 @@ import org.rhq.core.pluginapi.inventory.ProcessScanResult; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; import org.rhq.core.pluginapi.inventory.ManualAddFacet; -import org.rhq.core.pluginapi.migration.ResourceUpgradeContext; -import org.rhq.core.pluginapi.migration.ResourceUpgradeFacet; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeContext; +import org.rhq.core.pluginapi.upgrade.ResourceUpgradeFacet; import org.rhq.core.pluginapi.util.FileUtils; import org.rhq.core.system.ProcessInfo; import org.rhq.plugins.apache.parser.ApacheConfigReader;
commit 15bea470c93d5a59c69cd8bea3dc0f0c2a728a37 Author: Lukas Krejci lkrejci@redhat.com Date: Tue May 25 18:17:02 2010 +0200
Update the resource with upgrade data only if the upgrade data is not null.
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 8cc5280..feb2d81 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -1134,12 +1134,29 @@ public class InventoryManager extends AgentService implements ContainerService, }
if (serverUpdated) { - existingResource.setResourceKey(resourceKey); - existingResource.setName(name); - existingResource.setVersion(version); - existingResource.setDescription(description); - existingResource.setPluginConfiguration(pluginConfiguration); - existingResource.setResourceConfiguration(resourceConfiguration); + if (resourceKey != null) { + existingResource.setResourceKey(resourceKey); + } + + if (name != null) { + existingResource.setName(name); + } + + if (version != null) { + existingResource.setVersion(version); + } + + if (description != null) { + existingResource.setDescription(description); + } + + if (pluginConfiguration != null) { + existingResource.setPluginConfiguration(pluginConfiguration); + } + + if (resourceConfiguration != null) { + existingResource.setResourceConfiguration(resourceConfiguration); + } }
return serverUpdated;
commit 5c77f642a72f50fcb0c89613def447c39fcd1308 Author: Lukas Krejci lkrejci@redhat.com Date: Tue May 25 14:10:02 2010 +0200
First version of plugin-driven resource upgrade.
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java index f542f57..cfa2459 100644 --- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/discovery/DiscoveryServerService.java @@ -37,6 +37,7 @@ import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.ResourceErrorType; +import org.rhq.core.domain.resource.ResourceUpgradeReport;
/** * The interface to a JON server's resource discovery subsystem. @@ -137,6 +138,15 @@ public interface DiscoveryServerService { boolean updateResourceVersion(int resourceId, String version);
/** + * Upgrades the data of the resource according to the provided report. + * + * @param resourceId the id of the resource to be upgraded + * @param upgradeReport contains the information about the upgrade + * @return true if the upgrade succeeded, false otherwise. + */ + boolean upgradeResource(int resourceId, ResourceUpgradeReport upgradeReport); + + /** * Gives the server a chance to apply any necessary post-processing that's needed for newly committed resources * that have been successfully synchronized on the agent. * diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java new file mode 100644 index 0000000..52acf09 --- /dev/null +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceUpgradeReport.java @@ -0,0 +1,102 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.domain.resource; + +import java.io.Serializable; + +import org.rhq.core.domain.configuration.Configuration; + +/** + * Represents the changes that should be applied to the existing resource + * in order to upgrade it to conform to the new requirements set by the + * changed resource component. + * <p> + * Null values of the properties mean no change, non-null values represent + * the desired new values. + * + * @author Lukas Krejci + */ +public class ResourceUpgradeReport implements Serializable { + + private static final long serialVersionUID = 1L; + + private String newResourceKey; + private String newName; + private String newVersion; + private Configuration newPluginConfiguration; + private Configuration newResourceConfiguration; + private String newDescription; + + public ResourceUpgradeReport() { + + } + + public String getNewResourceKey() { + return newResourceKey; + } + + public void setNewResourceKey(String newResourceKey) { + this.newResourceKey = newResourceKey; + } + + public String getNewName() { + return newName; + } + + public void setNewName(String newName) { + this.newName = newName; + } + + public String getNewVersion() { + return newVersion; + } + + public void setNewVersion(String newVersion) { + this.newVersion = newVersion; + } + + public Configuration getNewPluginConfiguration() { + return newPluginConfiguration; + } + + public void setNewPluginConfiguration(Configuration newPluginConfiguration) { + this.newPluginConfiguration = newPluginConfiguration; + } + + public Configuration getNewResourceConfiguration() { + return newResourceConfiguration; + } + + public void setNewResourceConfiguration(Configuration newResourceConfiguration) { + this.newResourceConfiguration = newResourceConfiguration; + } + + public String getNewDescription() { + return newDescription; + } + + public void setNewDescription(String newDescription) { + this.newDescription = newDescription; + } +} diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeContext.java new file mode 100644 index 0000000..e8c5f03 --- /dev/null +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeContext.java @@ -0,0 +1,89 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.pluginapi.migration; + +import java.io.File; +import java.util.concurrent.Executor; + +import org.rhq.core.domain.configuration.Configuration; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.pluginapi.content.ContentContext; +import org.rhq.core.pluginapi.event.EventContext; +import org.rhq.core.pluginapi.inventory.PluginContainerDeployment; +import org.rhq.core.pluginapi.inventory.ResourceComponent; +import org.rhq.core.pluginapi.inventory.ResourceContext; +import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.operation.OperationContext; +import org.rhq.core.system.SystemInfo; + +/** + * Represents a resource during the resource upgrade phase of discovery. + * + * @see ResourceUpgradeFacet + * + * @author Lukas Krejci + */ +@SuppressWarnings("unchecked") +public class ResourceUpgradeContext<T extends ResourceComponent> extends ResourceContext<T> { + + private final Configuration resourceConfiguration; + private final String name; + private final String description; + + /** + * @see ResourceContext#ResourceContext(Resource, ResourceComponent, ResourceDiscoveryComponent, SystemInfo, File, File, String, EventContext, OperationContext, ContentContext, Executor, PluginContainerDeployment) + */ + public ResourceUpgradeContext(Resource resource, T parentResourceComponent, + ResourceDiscoveryComponent resourceDiscoveryComponent, SystemInfo systemInfo, File temporaryDirectory, + File dataDirectory, String pluginContainerName, EventContext eventContext, OperationContext operationContext, + ContentContext contentContext, Executor availCollectorThreadPool, + PluginContainerDeployment pluginContainerDeployment) { + + super(resource, parentResourceComponent, resourceDiscoveryComponent, systemInfo, temporaryDirectory, dataDirectory, + pluginContainerName, eventContext, operationContext, contentContext, availCollectorThreadPool, + pluginContainerDeployment); + + this.resourceConfiguration = resource.getResourceConfiguration(); + this.name = resource.getName(); + this.description = resource.getDescription(); + } + + public ResourceUpgradeContext(Resource resource, ResourceDiscoveryComponent discoveryComponent, ResourceContext<T> context, Executor availCollectorThreadPool) { + this(resource, context.getParentResourceComponent(), discoveryComponent, context.getSystemInformation(), context.getTemporaryDirectory(), + context.getDataDirectory(), context.getPluginContainerName(), context.getEventContext(), context.getOperationContext(), + context.getContentContext(), availCollectorThreadPool, context.getPluginContainerDeployment()); + } + + public Configuration getResourceConfiguration() { + return resourceConfiguration; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } +} diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeFacet.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeFacet.java new file mode 100644 index 0000000..df372bf --- /dev/null +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/migration/ResourceUpgradeFacet.java @@ -0,0 +1,58 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 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, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * 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 and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser 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.core.pluginapi.migration; + +import java.util.Map; +import java.util.Set; + +import org.rhq.core.domain.resource.ResourceUpgradeReport; +import org.rhq.core.pluginapi.inventory.ResourceComponent; + +/** + * This interface is to be implemented by discovery classes if they want to support + * upgrading the existing resources to a new format needed by an updated resource component. + * This is useful for example in the case when a new version of plugin redefined a resource + * key generation algorithm and wants to upgrade the legacy resources to use the new format. + * + * @author Lukas Krejci + */ +@SuppressWarnings("unchecked") +public interface ResourceUpgradeFacet<T extends ResourceComponent> { + + /** + * This method is called on the discovery component straight after it has finished the discovery. + * The exact same discovery results are passed to this method along with the set of resources + * that already exist in the inventory. + * + * @param inventoriedSimblings the existing resources + * @param parentContext the parent of both the newly discovered and existing resources + * @param discoveryResults the discovered resources. The resources from this set that have + * the same resource key as one of the inventoried siblings (after upgrade using the results of this method) won't + * be reported. + * @return the mapping of old resources to the newly desired data. The keys are instances from the + * inventoriedSiblings set, the values are the upgrade reports detailing what the data of the + * corresponding siblings should be upgraded to. + */ + Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSimblings, ResourceUpgradeContext<T> parentContext, Set<ResourceUpgradeContext> discoveryResults); +} diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/AutoDiscoveryExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/AutoDiscoveryExecutor.java index b84cdbc..e8abbbf 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/AutoDiscoveryExecutor.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/AutoDiscoveryExecutor.java @@ -183,7 +183,7 @@ public class AutoDiscoveryExecutor implements Runnable, Callable<InventoryReport List<ProcessScanResult> scanResults = performProcessScans(processInfos, serverType);
Set<Resource> discoveredServers = this.inventoryManager.executeComponentDiscovery(serverType, - component, platformComponent, platformContainer.getResourceContext(), scanResults); + component, platformContainer, scanResults);
for (Resource discoveredServer : discoveredServers) { log.debug("Detected server " + discoveredServer); diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 8944b99..8cc5280 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -70,6 +70,7 @@ import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.ResourceCreationDataType; import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.ResourceErrorType; +import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.pc.ContainerService; import org.rhq.core.pc.PluginContainer; @@ -104,6 +105,8 @@ import org.rhq.core.pluginapi.inventory.ResourceComponent; import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; +import org.rhq.core.pluginapi.migration.ResourceUpgradeContext; +import org.rhq.core.pluginapi.migration.ResourceUpgradeFacet; import org.rhq.core.pluginapi.operation.OperationContext; import org.rhq.core.pluginapi.operation.OperationServices; import org.rhq.core.system.SystemInfo; @@ -1110,6 +1113,38 @@ public class InventoryManager extends AgentService implements ContainerService, return resourceContainer.updateAvailability(availabilityType); }
+ private boolean mergeResourceFromUpgrade(Resource existingResource, ResourceUpgradeReport upgradeReport) { + String resourceKey = upgradeReport.getNewResourceKey(); + String name = upgradeReport.getNewName(); + String version = upgradeReport.getNewVersion(); + String description = upgradeReport.getNewDescription(); + Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); + Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration(); + + boolean serverUpdated = false; + try { + ServerServices serverServices = this.configuration.getServerServices(); + if (serverServices != null) { + DiscoveryServerService discoveryServerService = serverServices.getDiscoveryServerService(); + + serverUpdated = discoveryServerService.upgradeResource(existingResource.getId(), upgradeReport); + } + } catch (Exception e) { + log.error("Failed to upgrade the resource [" + existingResource + "] on the server.", e); + } + + if (serverUpdated) { + existingResource.setResourceKey(resourceKey); + existingResource.setName(name); + existingResource.setVersion(version); + existingResource.setDescription(description); + existingResource.setPluginConfiguration(pluginConfiguration); + existingResource.setResourceConfiguration(resourceConfiguration); + } + + return serverUpdated; + } + public Resource mergeResourceFromDiscovery(Resource resource, Resource parent) throws PluginContainerException { // If the Resource is already in inventory, make sure its version is up-to-date, then simply return the // existing Resource. @@ -1336,20 +1371,8 @@ public class InventoryManager extends AgentService implements ContainerService, parentComponent = getResourceComponent(resource.getParentResource()); }
- File pluginDataDir = new File(this.configuration.getDataDirectory(), resource.getResourceType().getPlugin()); - - ResourceContext context = new ResourceContext(resource, // the resource itself - parentComponent, // its parent component - discoveryComponent, // the discovery component (this is actually the proxy to it) - SystemInfoFactory.createSystemInfo(), // for native access - this.configuration.getTemporaryDirectory(), // location for plugin to write temp files - pluginDataDir, // location for plugin to write data files - this.configuration.getContainerName(), // the name of the agent/PC - getEventContext(resource), // for event access - getOperationContext(resource), // for operation manager access - getContentContext(resource), // for content manager access - this.availabilityCollectors, // for components that want to perform async avail checking - this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do + ResourceContext context = createResourceContext(resource, parentComponent, discoveryComponent); + container.setResourceContext(context);
// Wrap the component in a proxy that will provide locking and a timeout for the call to start(). @@ -1396,6 +1419,23 @@ public class InventoryManager extends AgentService implements ContainerService, } }
+ private <T extends ResourceComponent> ResourceContext<T> createResourceContext(Resource resource, T parentComponent, ResourceDiscoveryComponent<T> discoveryComponent) { + File pluginDataDir = new File(this.configuration.getDataDirectory(), resource.getResourceType().getPlugin()); + + return new ResourceContext<T>(resource, // the resource itself + parentComponent, // its parent component + discoveryComponent, // the discovery component (this is actually the proxy to it) + SystemInfoFactory.createSystemInfo(), // for native access + this.configuration.getTemporaryDirectory(), // location for plugin to write temp files + pluginDataDir, // location for plugin to write data files + this.configuration.getContainerName(), // the name of the agent/PC + getEventContext(resource), // for event access + getOperationContext(resource), // for operation manager access + getContentContext(resource), // for content manager access + this.availabilityCollectors, // for components that want to perform async avail checking + this.configuration.getPluginContainerDeployment()); // helps components make determinations of what to do + } + /** * This will send a resource error to the server (if applicable) to indicate that the given resource could not be * connected to due to an invalid plugin configuration. @@ -1960,8 +2000,12 @@ public class InventoryManager extends AgentService implements ContainerService,
@NotNull Set<Resource> executeComponentDiscovery(ResourceType resourceType, ResourceDiscoveryComponent discoveryComponent, - ResourceComponent parentComponent, ResourceContext parentResourceContext, - List<ProcessScanResult> processScanResults) { + ResourceContainer parentContainer, List<ProcessScanResult> processScanResults) { + + ResourceContext parentResourceContext = parentContainer.getResourceContext(); + ResourceComponent parentComponent = parentContainer.getResourceComponent(); + Resource parentResource = parentContainer.getResource(); + long startTime = System.currentTimeMillis(); log.debug("Executing discovery for [" + resourceType.getName() + "] Resources..."); Set<Resource> newResources; @@ -2000,6 +2044,59 @@ public class InventoryManager extends AgentService implements ContainerService, newResources.add(newResource); } } + + //check for upgrade support + if (discoveryComponent instanceof ResourceUpgradeFacet) { + ResourceUpgradeFacet resourceUpgrade = (ResourceUpgradeFacet) discoveryComponent; + + Set<Resource> siblings = getResourcesWithType(resourceType, parentResource.getChildResources()); + + Resource grandParent = parentResource.getParentResource(); + ResourceContainer grandParentContainer = grandParent == null ? null : getResourceContainer(grandParent); + ResourceDiscoveryComponent parentDiscoveryComponent = PluginContainer.getInstance().getPluginComponentFactory() + .getDiscoveryComponent(parentResource.getResourceType(), grandParentContainer); + + ResourceUpgradeContext<?> parentUpgradeContext = new ResourceUpgradeContext(parentResource, parentDiscoveryComponent, parentResourceContext, availabilityCollectors); + + Set<ResourceUpgradeContext> siblingContexts = new HashSet<ResourceUpgradeContext>(siblings.size()); + + Map<ResourceUpgradeContext, Resource> siblingContextToResource = new HashMap<ResourceUpgradeContext, Resource>(); + + for (Resource sibling : siblings) { + ResourceUpgradeContext siblingContext = new ResourceUpgradeContext(sibling, discoveryComponent, getResourceContainer(sibling).getResourceContext(), availabilityCollectors); + siblingContexts.add(siblingContext); + siblingContextToResource.put(siblingContext, sibling); + } + + Set<ResourceUpgradeContext> newResourceContexts = new HashSet<ResourceUpgradeContext>(); + Map<String, Resource> newResourceKeyToResource = new HashMap<String, Resource>(); + + for (Resource newResource : newResources) { + ResourceUpgradeContext newUpgradeContext = new ResourceUpgradeContext(newResource, discoveryComponent, createResourceContext(newResource, parentComponent, discoveryComponent), availabilityCollectors); + newResourceContexts.add(newUpgradeContext); + newResourceKeyToResource.put(newResource.getResourceKey(), newResource); + } + + Map<ResourceUpgradeContext, ResourceUpgradeReport> results = resourceUpgrade.upgrade(siblingContexts, parentUpgradeContext, newResourceContexts); + + for(Map.Entry<ResourceUpgradeContext, ResourceUpgradeReport> upgradeEntry : results.entrySet()) { + Resource siblingToUpgrade = siblingContextToResource.get(upgradeEntry.getKey()); + ResourceUpgradeReport newData = upgradeEntry.getValue(); + + mergeResourceFromUpgrade(siblingToUpgrade, newData); + + //if there was a resource key upgrade, remove a resource with the same resource key + //from the discovery results. Otherwise we'd end up with 2 sibling resources with + //the same resource key, which is illegal. + if (newData.getNewResourceKey() != null) { + Resource newResourceToRemove = newResourceKeyToResource.get(newData.getNewResourceKey()); + if (newResourceToRemove != null) { + newResources.remove(newResourceToRemove); + } + } + } + } + } catch (Throwable e) { // TODO GH: Add server/parent - up/down semantics so this won't happen just because a server is not up long elapsedTime = System.currentTimeMillis() - startTime; diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/RuntimeDiscoveryExecutor.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/RuntimeDiscoveryExecutor.java index c16ba56..c60d4a8 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/RuntimeDiscoveryExecutor.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/RuntimeDiscoveryExecutor.java @@ -43,8 +43,11 @@ import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.pc.PluginContainer; import org.rhq.core.pc.PluginContainerConfiguration; import org.rhq.core.pc.plugin.PluginComponentFactory; +import org.rhq.core.pluginapi.inventory.ProcessScanResult; import org.rhq.core.pluginapi.inventory.ResourceComponent; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; +import org.rhq.core.pluginapi.migration.ResourceUpgradeContext; +import org.rhq.core.pluginapi.migration.ResourceUpgradeFacet; import org.rhq.core.util.exception.ExceptionPackage; import org.rhq.core.util.exception.Severity;
@@ -237,8 +240,8 @@ public class RuntimeDiscoveryExecutor implements Runnable, Callable<InventoryRep + childResourceType + "]"); } Set<Resource> childResources = this.inventoryManager.executeComponentDiscovery(childResourceType, - discoveryComponent, parentComponent, parentContainer.getResourceContext(), Collections.EMPTY_LIST); - + discoveryComponent, parentContainer, Collections.<ProcessScanResult>emptyList()); + // For each discovered resource, update it in the inventory manager and recursively discover its child resources Map<String, Resource> mergedResources = new HashMap<String, Resource>();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java index cded63b..2d3e9e6 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java @@ -56,6 +56,7 @@ import org.rhq.core.domain.resource.ProductVersion; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.core.domain.util.PageOrdering; @@ -400,6 +401,19 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot } }
+ public boolean upgradeResource(int resourceId, ResourceUpgradeReport upgradeReport) { + Resource existingResource = this.entityManager.find(Resource.class, resourceId); + if (existingResource != null) { + boolean changed = upgradeResource(existingResource, upgradeReport); + if (changed) { + this.entityManager.merge(existingResource); + } + return true; + } else { + return false; + } + } + /** * Convienence method that looks at <code>resource</code> and if its version is not * the same as <code>newVersion</code>, its version string will be set to it. If @@ -445,6 +459,81 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot return versionChanged; }
+ /** + * @param existingResource + * @param upgradeReport + * @return + */ + private boolean upgradeResource(Resource resource, ResourceUpgradeReport upgradeReport) { + boolean changed = false; + if (resource != null) { + String resourceKey = upgradeReport.getNewResourceKey(); + String name = upgradeReport.getNewName(); + String version = upgradeReport.getNewVersion(); + String description = upgradeReport.getNewDescription(); + Configuration pluginConfiguration = upgradeReport.getNewPluginConfiguration(); + Configuration resourceConfiguration = upgradeReport.getNewResourceConfiguration(); + + if (resourceKey != null) { + if (!equalOrNull(resourceKey, resource.getResourceKey())) { + log.info("Resource [" + resource + "] upgraded its resource key from [" + + resource.getResourceKey() + "] to [" + resourceKey + "]"); + changed = true; + resource.setResourceKey(resourceKey); + } + } + + if (name != null) { + if (!equalOrNull(name, resource.getName())) { + log.info("Resource [" + resource + "] upgraded its name from [" + + resource.getName() + "] to [" + name + "]"); + changed = true; + resource.setName(name); + } + } + + if (version != null) { + changed = updateResourceVersion(resource, version) || changed; + } + + if (description != null) { + if (!equalOrNull(description, resource.getDescription())) { + log.info("Resource [" + resource + "] upgraded its description from [" + + resource.getDescription() + "] to [" + description + "]"); + changed = true; + resource.setDescription(description); + } + } + + if (pluginConfiguration != null) { + if (!equalOrNull(pluginConfiguration, resource.getPluginConfiguration())) { + log.info("Resource [" + resource + "] upgraded its plugin configuration from [" + + resource.getPluginConfiguration() + "] to [" + pluginConfiguration + "]"); + changed = true; + resource.setPluginConfiguration(pluginConfiguration); + } + } + + if (resourceConfiguration != null) { + if (!equalOrNull(resourceConfiguration, resource.getResourceConfiguration())) { + //XXX Will this create a new history entry? + + log.info("Resource [" + resource + "] upgraded its resource configuration from [" + + resource.getResourceConfiguration() + "] to [" + resourceConfiguration + "]"); + + changed = true; + resource.setResourceConfiguration(resourceConfiguration); + } + } + + // If the resource was marked as deleted, reactivate it again. + if (resource.getInventoryStatus() == InventoryStatus.DELETED) { + resource.setInventoryStatus(InventoryStatus.COMMITTED); + } + } + return changed; + } + private void validateInventoryReport(InventoryReport report) throws InvalidInventoryReportException { for (Resource root : report.getAddedRoots()) { validateResource(root); @@ -793,4 +882,16 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot
updateInventoryStatus(subject, platforms, servers, target); } + + private static <T> boolean equalOrNull(T a, T b) { + if (a == null) { + return b == null; + } else { + if (b == null) { + return false; + } else { + return a.equals(b); + } + } + } } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java index 01394b9..4e60ffb 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossLocal.java @@ -38,6 +38,7 @@ import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList;
@@ -176,4 +177,13 @@ public interface DiscoveryBossLocal extends DiscoveryBossRemote { * <code>false</code> if the Resource was not in inventory */ boolean updateResourceVersion(int resourceId, String version); + + /** + * Upgrades the data of the resource according to the provided report. + * + * @param resourceId the id of the resource to be upgraded + * @param upgradeReport contains the information about the upgrade + * @return true if the upgrade succeeded, false otherwise. + */ + boolean upgradeResource(int resourceId, ResourceUpgradeReport upgradeReport); } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java index d692ad8..720465e 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java @@ -37,6 +37,7 @@ import org.rhq.core.domain.resource.Agent; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceError; +import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.util.collection.ArrayUtils; import org.rhq.core.util.exception.ThrowableUtil; import org.rhq.enterprise.server.alert.AlertDefinitionCreationException; @@ -176,6 +177,11 @@ public class DiscoveryServerServiceImpl implements DiscoveryServerService { return discoveryBoss.updateResourceVersion(resourceId, version); }
+ public boolean upgradeResource(int resourceId, ResourceUpgradeReport upgradeReport) { + DiscoveryBossLocal discoveryBoss = LookupUtil.getDiscoveryBoss(); + return discoveryBoss.upgradeResource(resourceId, upgradeReport); + } + private static Resource convertToPojoResource(Resource resource, boolean includeDescendants) { Resource pojoResource = new Resource(resource.getId()); pojoResource.setUuid(resource.getUuid()); diff --git a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java index 8f6deb7..4d80ac1 100644 --- a/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java +++ b/modules/plugins/apache/src/main/java/org/rhq/plugins/apache/ApacheServerDiscoveryComponent.java @@ -21,8 +21,10 @@ package org.rhq.plugins.apache; import java.io.File; import java.io.IOException; import java.net.URI; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set;
import org.apache.commons.logging.Log; @@ -36,12 +38,16 @@ import org.rhq.augeas.util.GlobFilter; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.Property; import org.rhq.core.domain.configuration.PropertySimple; +import org.rhq.core.domain.resource.ResourceUpgradeReport; import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails; import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; import org.rhq.core.pluginapi.inventory.ManualAddFacet; import org.rhq.core.pluginapi.inventory.ProcessScanResult; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent; import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext; +import org.rhq.core.pluginapi.inventory.ManualAddFacet; +import org.rhq.core.pluginapi.migration.ResourceUpgradeContext; +import org.rhq.core.pluginapi.migration.ResourceUpgradeFacet; import org.rhq.core.pluginapi.util.FileUtils; import org.rhq.core.system.ProcessInfo; import org.rhq.plugins.apache.parser.ApacheConfigReader; @@ -63,7 +69,8 @@ import org.rhq.rhqtransform.impl.PluginDescriptorBasedAugeasConfiguration; * @author Ian Springer * @author Lukas Krejci */ -public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponent<PlatformComponent>, ManualAddFacet<PlatformComponent> { +public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponent<PlatformComponent>, ManualAddFacet<PlatformComponent>, + ResourceUpgradeFacet<PlatformComponent> { private static final String PRODUCT_DESCRIPTION = "Apache Web Server";
private static final Log log = LogFactory.getLog(ApacheServerDiscoveryComponent.class); @@ -163,7 +170,46 @@ public class ApacheServerDiscoveryComponent implements ResourceDiscoveryComponen return discoveredResources; }
- + public Map<ResourceUpgradeContext, ResourceUpgradeReport> upgrade(Set<ResourceUpgradeContext> inventoriedSimblings, + ResourceUpgradeContext<PlatformComponent> parentContext, Set<ResourceUpgradeContext> discoveryResults) { + + Map<ResourceUpgradeContext, ResourceUpgradeReport> ret = new HashMap<ResourceUpgradeContext, ResourceUpgradeReport>(); + + for (ResourceUpgradeContext context : inventoriedSimblings) { + String inventoriedResourceKey = context.getResourceKey(); + File inventoriedResourceKeyAsPath = new File(inventoriedResourceKey); + + //the resource key we use now is a full path to the httpdconf. + //in the old version, it was the server root. + //so if the inventoried resource key is a path to a file, + //we know it's a new style resource key. + if (inventoriedResourceKeyAsPath.isFile()) { + continue; + } + + Configuration pluginConfiguration = context.getPluginConfiguration(); + + String serverRoot = pluginConfiguration.getSimpleValue("serverRoot", null); + String httpdConf = pluginConfiguration.getSimpleValue("configFile", null); + + String resourceKey = null; + + if (httpdConf != null) { + File httpdConfFile = new File(httpdConf); + if (!httpdConfFile.isAbsolute()) { + httpdConfFile = new File(serverRoot, httpdConf); + } + + resourceKey = httpdConfFile.getPath(); + + ResourceUpgradeReport rep = new ResourceUpgradeReport(); + rep.setNewResourceKey(resourceKey); + + ret.put(context, rep); + } + } + return ret; + }
public DiscoveredResourceDetails discoverResource(Configuration pluginConfig, ResourceDiscoveryContext<PlatformComponent> discoveryContext)
rhq-commits@lists.fedorahosted.org