All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rhq.server.control.command.Upgrade Maven / Gradle / Ivy

The newest version!
/*
 *
 * RHQ Management Platform
 * Copyright (C) 2005-2014 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.server.control.command;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Future;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;

import org.rhq.core.util.PropertiesFileUpdate;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.file.FileReverter;
import org.rhq.core.util.file.FileUtil;
import org.rhq.core.util.obfuscation.ObfuscatedPreferences.RestrictedFormat;
import org.rhq.core.util.obfuscation.PicketBoxObfuscator;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.server.control.ControlCommand;
import org.rhq.server.control.RHQControl;
import org.rhq.server.control.RHQControlException;
import org.rhq.server.control.util.ExecutorAssist;

/**
 * @author Jay Shaughnessy
 * @author John Mazzitelli
 * @author Heiko W. Rupp
 */
public class Upgrade extends AbstractInstall {

    private static final String FROM_SERVER_DIR_OPTION = "from-server-dir";
    private static final String USE_REMOTE_STORAGE_NODE = "use-remote-storage-node";
    private static final String STORAGE_DATA_ROOT_DIR = "storage-data-root-dir";
    private static final String LIST_VERSIONS_OPTION = "list-versions";
    private static final String STORAGE_SCHEMA_OPTION = "storage-schema";

    private Options options;

    public Upgrade() {
        options = new Options()
            .addOption(
                null,
                FROM_AGENT_DIR_OPTION,
                true,
                "Full path to install directory of the RHQ Agent to be upgraded. Required only if an existing agent "
                    + "exists and is not installed in the default location: /../rhq-agent")
            .addOption(null, FROM_SERVER_DIR_OPTION, true,
                "Full path to install directory of the RHQ Server to be upgraded. Required.")
            .addOption(null, START_OPTION, false,
                "Deprecated.  This option has no effect and will be removed in a future version.")
            .addOption(
                null,
                USE_REMOTE_STORAGE_NODE,
                true,
                "By default a server is co-located with a storage node. However, if this option is set to true, no local "
                    + "storage node will be upgraded and it is assumed a remote storage node is configured in rhq-server.properties.")
            .addOption(
                null,
                LIST_VERSIONS_OPTION,
                false,
                "This option prints the install versions for the Servers and Storage Nodes in the topology. This option must be run "
                    + "from an already installed or upgraded RHQ Server node. When specified, all other options are ignored. ")
            .addOption(
                null,
                STORAGE_DATA_ROOT_DIR,
                true,
                "This option is valid only when upgrading from older systems that did not have storage nodes. Use this option to specify a non-default base "
                    + "directory for the data directories created by the storage node. For example, if the default directory is "
                    + "not writable for the current user (/var/lib on Linux) or if you simply prefer a different location. ")
            .addOption(
                null,
                STORAGE_SCHEMA_OPTION,
                false,
                "This option updates the storage cluster schema.  This option must be run from an RHQ Server node. The running time for "
                    + "the schema update will vary depending on the schema changes being made, the runtime may be long and should not be "
                    + "interrupted.  It requires that all servers and storage nodes have already been upgraded to the desired version "
                    + "and that all nodes in the storage cluster are running. The command will fail if these prerequisites are not met. "
                    + "Use 'rhqctl upgrade --list-versions' to see the current upgrade status.  When specified, all other options "
                    + "are ignored.  Not all upgrades will require this step.");
    }

    @Override
    public String getName() {
        return "upgrade";
    }

    @Override
    public String getDescription() {
        return "Upgrades RHQ services from an earlier installed version";
    }

    @Override
    public Options getOptions() {
        return options;
    }

    @Override
    protected String getReadmeFilename() {
        return "UPGRADE_README.txt";
    }

    @Override
    protected int exec(CommandLine commandLine) {
        if (commandLine.hasOption(LIST_VERSIONS_OPTION)) {
            return listVersions(commandLine);
        }

        if (commandLine.hasOption(STORAGE_SCHEMA_OPTION)) {
            return updateStorageSchema(commandLine);
        }

        int rValue = RHQControl.EXIT_CODE_OK;

        List errors = null;
        try {
            errors = validateOptions(commandLine);
            if (!errors.isEmpty()) {
                for (String error : errors) {
                    log.error(error);
                }
                log.error("Exiting due to the previous errors");
                return RHQControl.EXIT_CODE_OPERATION_FAILED;
            }

            // If storage or server appear to be installed already then don't perform an upgrade.  It's OK
            // if the agent already exists in the default location, it may be there from a prior install.
            if (isStorageInstalled() || isServerInstalled()) {
                log.warn("RHQ is already installed so upgrade can not be performed.");
                return RHQControl.EXIT_CODE_OPERATION_FAILED;
            }

            // Attempt to shutdown any running components. A failure to shutdown a component is not a failure as it
            // really shouldn't be running anyway. This is just an attempt to avoid upgrade problems.
            log.info("Stopping any running RHQ components...");

            // Stop the agent, if running.
            if (commandLine.hasOption(FROM_AGENT_DIR_OPTION)) {
                rValue = Math.max(rValue, killAgent(getFromAgentDir(commandLine))); // this validates the path as well
            }

            // If rhqctl exists in the old version, use it to stop old components, otherwise, just try and stop the
            // server using the legacy script. If there is no rhqctl, there is no storage node anyway, so we just
            // stop server in that case.
            File fromBinDir = new File(getFromServerDir(commandLine), "bin");
            org.apache.commons.exec.CommandLine rhqctlStop = isRhq48OrLater(commandLine) ? getCommandLine(false,
                "rhqctl", "stop") : getCommandLine("rhq-server", "stop");

            int exitValue = ExecutorAssist.execute(fromBinDir, rhqctlStop);
            if (exitValue == 0) {
                log.info("The old installation components have been stopped");
            } else {
                log.error("The old installation components failed to be stopped. Please stop them manually before continuing. exit code="
                    + exitValue);
                return exitValue;
            }

            // If any failures occur during upgrade, we know we need to reset rhq-server.properties
            final FileReverter serverPropFileReverter = new FileReverter(getServerPropertiesFile());
            addUndoTask(new ControlCommand.UndoTask("Reverting server properties file ["
                + getServerPropertiesFile().getName() + "]") {
                public void performUndoWork() throws Exception {
                    try {
                        serverPropFileReverter.revert();
                    } catch (Exception e) {
                        throw new Exception("Cannot reset rhq-server.properties - revert settings manually", e);
                    }
                }
            });

            // now upgrade everything
            upgradeServerEnvFile(commandLine);
            rValue = Math.max(rValue, upgradeStorage(commandLine));
            rValue = Math.max(rValue, upgradeServer(commandLine));
            rValue = Math.max(rValue, upgradeAgent(commandLine));

            File agentDir;

            if (commandLine.hasOption(FROM_AGENT_DIR_OPTION)) {
                agentDir = new File(commandLine.getOptionValue(FROM_AGENT_DIR_OPTION));
            } else {
                agentDir = getAgentBasedir();
            }

            updateWindowsAgentService(agentDir);

        } catch (Exception e) {
            throw new RHQControlException("An error occurred while executing the upgrade command", e);

        } finally {
            if (errors == null || errors.isEmpty()) {
                try {
                    if (isServerInstalled()) {
                        log.info("\n\n========== UPGRADE SUMMARY ==========");
                        listVersions(commandLine);
                    }

                    Stop stopCommand = new Stop();
                    stopCommand.exec(new String[] { "--server" });
                    rValue = Math.max(rValue, stopCommand.exec(new String[] { "--storage" }));

                } catch (Throwable t) {
                    log.warn("Unable to stop services: " + t.getMessage());
                    rValue = RHQControl.EXIT_CODE_OPERATION_FAILED;
                }
            }
        }

        return rValue;
    }

    private int upgradeStorage(CommandLine rhqctlCommandLine) throws Exception {
        if (rhqctlCommandLine.hasOption(USE_REMOTE_STORAGE_NODE)) {
            log.info("Ignoring storage node upgrade, a remote storage node is configured.");
            return RHQControl.EXIT_CODE_OK;
        }

        int rValue = RHQControl.EXIT_CODE_OK;

        // If upgrading from a pre-cassandra then just install an initial storage node. Otherwise, upgrade
        if (isRhq48OrLater(rhqctlCommandLine)) {
            try {
                final String fromServerPath = getFromServerDir(rhqctlCommandLine).getAbsolutePath();

                // We need to be sure the storage is really stopped (long enough) to not get a port conflict
                waitForProcessToStop(getStoragePid());

                // if the upgrade fails, we need to purge the new storage node basedir to allow for user to try again
                // later
                addUndoTask(new ControlCommand.UndoTask("Removing new storage node install directory") {
                    public void performUndoWork() {
                        try {
                            org.apache.commons.exec.CommandLine commandLine = getCommandLine("rhq-storage-installer",
                                "--undo", fromServerPath);
                            ExecutorAssist.execute(getBinDir(), commandLine);
                        } catch (Exception e) {
                            log.warn("Unable to undo version stamp for storage node: " + e.getMessage());
                        }
                        FileUtil.purge(getStorageBasedir(), true);
                    }
                });
                addUndoTaskToStopComponent("--storage"); // The undo tasks are done in reversed order

                org.apache.commons.exec.CommandLine commandLine = getCommandLine("rhq-storage-installer", "--upgrade",
                    fromServerPath);

                rValue = ExecutorAssist.execute(getBinDir(), commandLine);
                log.info("The storage node upgrade has finished with an exit value of [" + rValue + "]");

            } catch (IOException e) {
                log.error("An error occurred while running the storage node upgrade: " + e.getMessage());
                throw e;
            }

        } else {
            rValue = installStorageNode(getStorageBasedir(), rhqctlCommandLine, true);
        }

        // Only an exception will stop the upgrade progress and invoke the undo logic.
        if (rValue != RHQControl.EXIT_CODE_OK) {
            throw new RuntimeException("The storage node upgrade failed with exit code [" + rValue + "]");
        }

        return RHQControl.EXIT_CODE_OK;
    }

    private int upgradeServer(CommandLine commandLine) throws Exception {
        // don't upgrade the server if this is a storage node only install
        File oldServerDir = getFromServerDir(commandLine);
        if (!(!isRhq48OrLater(commandLine) || isServerInstalled(oldServerDir))) {
            log.info("Ignoring server upgrade, the '--from-server-dir' is a storage node only installation.");
            return RHQControl.EXIT_CODE_OK;
        }

        // copy all the old settings into the new rhq-server.properties file
        upgradeServerPropertiesFile(commandLine);

        int rValue = RHQControl.EXIT_CODE_OK;
        // make sure we retain the oracle driver if one exists
        try {
            copyOracleDriver(oldServerDir);
        } catch (Exception e) {
            log.error("Failed to copy the old Oracle driver to the new server. "
                + "The upgrade will continue but your server may not work if connecting to an Oracle database, "
                + "in which case you will need to manually install an Oracle driver to your server. " + "Cause: "
                + ThrowableUtil.getAllMessages(e));
            rValue = RHQControl.EXIT_CODE_OPERATION_FAILED;
        }

        // copy over any wrapper.inc that may have been added
        File oldWrapperIncFile = new File(oldServerDir, "bin/wrapper/rhq-server-wrapper.inc");
        if (oldWrapperIncFile.exists()) {
            File newWrapperIncFile = new File(getBaseDir(), "bin/wrapper/rhq-server-wrapper.inc");
            FileUtil.copyFile(oldWrapperIncFile, newWrapperIncFile);
        }

        // start the server, then invoke the installer and wait for the server to be completely installed
        rValue = Math.max(rValue, startRHQServerForInstallation());
        Future integerFuture = runRHQServerInstaller(ServerInstallerAction.UPGRADE);
        waitForRHQServerToInitialize(integerFuture);

        rValue = Math.max(rValue, integerFuture.get());
        return rValue;
    }

    public void copyOracleDriver(File oldServerDir) throws IOException {
        // RHQ doesn't ship the Oracle driver. If the user uses Oracle, they have their own driver so we need to copy it over.
        // Because the module.xml has the driver name in it, we need to copy the full Oracle JDBC driver module content.
        // Look in the new server install and see if we do not have a real oracle JDBC driver.
        // If the new server only has our "dummy" driver, we copy over the old driver module to the new server.
        // If the new server already has a "real" driver, leave anything else in place as it may be a newer driver.
        String oracleModuleRelativePath = "modules/org/rhq/oracle";
        File newOracleModuleDir = new File(getBaseDir(), oracleModuleRelativePath);
        File newOracleModuleMainDir = new File(newOracleModuleDir, "main");

        // first see if the new server was already given a real oracle driver - if so, there is nothing for us to do
        for (File f : newOracleModuleMainDir.listFiles()) {
            boolean foundRealOracleDriver = f.isFile() && f.length() > 100000L; // the actual driver is much bigger, our fake one is small
            if (foundRealOracleDriver == true) {
                log.info("Looks like the new server already has an Oracle driver: " + f);
                return; // nothing for us to do since the new server already appears to have a real oracle driver
            }
        }

        // now see if we are updating a newer JBossAS7+ based server - if so, the old oracle driver is in a module
        File oldOracleModuleDir = new File(oldServerDir, oracleModuleRelativePath);
        if (oldOracleModuleDir.isDirectory()) {
            FileUtil.purge(newOracleModuleDir, true); // clean out anything that might be in here
            FileUtil.copyDirectory(oldOracleModuleDir, newOracleModuleDir);
            log.info("Copied the old Oracle JDBC module [" + oldOracleModuleDir + "] to the new server: "
                + newOracleModuleDir);
        } else {
            // we aren't updating a newer JBossAS7+ based server, its probably an older JBossAS 4.2.3 based server
            // where the oracle jar is located in a different directory (jbossas/server/default/lib/ojdbc*.jar)
            File oldLibDir = new File(oldServerDir, "jbossas/server/default/lib");
            if (oldLibDir.isDirectory()) {
                FilenameFilter oracleDriverFilenameFilter = new FilenameFilter() {
                    public boolean accept(File dir, String name) {
                        return name.startsWith("ojdbc") && name.endsWith(".jar");
                    }
                };
                // find the old ojdbc driver
                File[] oracleDriver = oldLibDir.listFiles(oracleDriverFilenameFilter);
                if (oracleDriver != null && oracleDriver.length > 0) {
                    if (oracleDriver.length > 1) {
                        log.warn("It appears that more than one oracle driver exists in the old server at ["
                            + oldLibDir + "]; this one will be reused: " + oracleDriver[0]);
                    }
                    // we need to remove the dummy oracle driver file from the new server first
                    File[] dummy = newOracleModuleMainDir.listFiles(oracleDriverFilenameFilter);
                    if (dummy != null) {
                        for (File dummyFileToDelete : dummy) { // there should only be one, but just remove all ojdbc*.jar files
                            dummyFileToDelete.delete();
                        }
                    }
                    // copy the real oracle driver to our new server's oracle module
                    File newOracleJarFile = new File(newOracleModuleMainDir, oracleDriver[0].getName());
                    FileUtil.copyFile(oracleDriver[0], newOracleJarFile);
                    log.info("Copied the old Oracle JDBC driver [" + oracleDriver[0] + "] to the new server: "
                        + newOracleJarFile);

                    // now we need to update the module.xml file so it points to the new oracle driver
                    File moduleXmlFile = new File(newOracleModuleMainDir, "module.xml");
                    String originalXml = new String(StreamUtil.slurp(new FileInputStream(moduleXmlFile)));
                    String newXml = originalXml.replaceFirst("resource-root path.*=.*\"ojdbc.*jar\"",
                        "resource-root path=\"" + oracleDriver[0].getName() + "\"");
                    FileUtil.writeFile(new ByteArrayInputStream(newXml.getBytes()), moduleXmlFile);
                    log.info("Updated module.xml [" + moduleXmlFile + "] to use the proper Oracle driver");
                }
            }
        }

        return;
    }

    /**
     * If there is an rhq-server-env.sh|bat file in the old server directory then:
     *   1) backup the new version as rhq.server-env.sh|bat.default.
     *   2) copy the old version to the new server so it can be applied to the upgrade.
     * 
* @param commandLine * @throws Exception */ private void upgradeServerEnvFile(CommandLine commandLine) throws Exception { File oldServerDir = getFromServerDir(commandLine); String[] envFiles = new String[] { "bin/rhq-server-env.sh", "bin/rhq-server-env.bat" }; for (String envFile : envFiles) { File oldServerEnvFile = new File(oldServerDir, envFile); if (oldServerEnvFile.exists()) { File newServerEnvFile = new File(getBaseDir(), envFile); File newServerEnvFileBackup = new File(getBaseDir(), (envFile + ".default")); try { // If any failures occur during upgrade reset the env file to the default final FileReverter serverEnvFileReverter = new FileReverter(newServerEnvFile); addUndoTask(new ControlCommand.UndoTask("Reverting server environment file [" + newServerEnvFile.getName() + "]") { public void performUndoWork() throws Exception { try { serverEnvFileReverter.revert(); } catch (Exception e) { throw new Exception("Cannot reset rhq-server-env.sh|bat - revert manually", e); } } }); FileUtil.copyFile(newServerEnvFile, newServerEnvFileBackup); newServerEnvFile.delete(); FileUtil.copyFile(oldServerEnvFile, newServerEnvFile); } catch (Exception e) { // log a message about this problem, but we will let the upgrade continue log.error("Failed to update [" + oldServerEnvFile + "] to [" + newServerEnvFile + "]. Settings in + [" + oldServerEnvFile + "] + will not be applied to the upgrade. " + "You will need to manually copy the file to the new location after the upgrade."); } } } return; } private void upgradeServerPropertiesFile(CommandLine commandLine) throws Exception { File oldServerDir = getFromServerDir(commandLine); File oldServerPropsFile = new File(oldServerDir, "bin/rhq-server.properties"); Properties oldServerProps = new Properties(); FileInputStream oldServerPropsFileInputStream = new FileInputStream(oldServerPropsFile); try { oldServerProps.load(oldServerPropsFileInputStream); } finally { oldServerPropsFileInputStream.close(); } oldServerProps.setProperty("rhq.autoinstall.enabled", "true"); // ensure that we always enable the installer oldServerProps.setProperty("rhq.autoinstall.database", "auto"); // the old value could have been "overwrite" - NOT what we want when upgrading // For upgrades the RHQ Server super-user should already exist. But to pass server properties file validation // this property must be set. Setting it to an invalid plain-text value will fail the upgrade if for some reason // the rhqadmin user does not exist, which is, I think, what we would want to have happen. oldServerProps.setProperty("rhq.autoinstall.server.admin.password", "ignored-on-upgrade"); // remove some old, obsolete settings no longer needed or used oldServerProps.remove("rhq.server.embedded-agent.name"); oldServerProps.remove("rhq.server.embedded-agent.reset-configuration"); oldServerProps.remove("rhq.server.embedded-agent.disable-native-system"); oldServerProps.remove("rhq.server.embedded-agent.enabled"); oldServerProps.remove("rhq.server.startup.jrmpinvoker.rmiport"); oldServerProps.remove("rhq.server.startup.webservice.port"); oldServerProps.remove("rhq.server.startup.unifiedinvoker.port"); oldServerProps.remove("rhq.server.startup.namingservice.rmiport"); oldServerProps.remove("rhq.server.startup.pooledinvoker.rmiport"); oldServerProps.remove("rhq.server.startup.ajp.port"); oldServerProps.remove("rhq.server.startup.namingservice.port"); oldServerProps.remove("rhq.server.startup.aspectdeployer.bind-port"); oldServerProps.remove("rhq.server.plugin-deployer-threads"); oldServerProps.remove("rhq.server.database.xa-datasource-class"); oldServerProps.remove("rhq.server.database.driver-class"); oldServerProps.remove("java.rmi.server.hostname"); // do not set the keystore/truststore algorithms if they are the defaults to allow for runtime defaults to take effect String[] algPropNames = new String[] { "rhq.communications.connector.security.truststore.algorithm", // "rhq.communications.connector.security.keystore.algorithm", // "rhq.server.client.security.keystore.algorithm", // "rhq.server.client.security.truststore.algorithm", // "rhq.server.tomcat.security.algorithm" }; for (String algPropName : algPropNames) { String algValue = oldServerProps.getProperty(algPropName, "SunX509"); if (algValue.equals("SunX509") || algValue.equals("IbmX509")) { oldServerProps.remove(algPropName); // let the default take effect at runtime - which will depend on the JVM } } // the older servers stored the HTTP and HTTPS ports under different names - make sure we reuse those ports with the new properties String httpPort = oldServerProps.getProperty("rhq.server.startup.web.http.port"); if (httpPort != null) { oldServerProps.remove("rhq.server.startup.web.http.port"); oldServerProps.setProperty("rhq.server.socket.binding.port.http", httpPort); } String httpsPort = oldServerProps.getProperty("rhq.server.startup.web.https.port"); if (httpsPort != null) { oldServerProps.remove("rhq.server.startup.web.https.port"); oldServerProps.setProperty("rhq.server.socket.binding.port.https", httpsPort); } //Migrate storage node properties String storageUsername = oldServerProps.getProperty("rhq.cassandra.username"); if (storageUsername != null) { oldServerProps.remove("rhq.cassandra.username"); oldServerProps.setProperty("rhq.storage.username", storageUsername); } String storagePassword = oldServerProps.getProperty("rhq.cassandra.password"); if (storagePassword != null) { // In RHQ 4.8 the Cassandra username/password had to be rhqadmin/rhqadmin; so, // we can safely set rhq.storage.password to the obfuscated version freeing the // user of performing the additional step of generated the obfuscated password. oldServerProps.remove("rhq.cassandra.password"); oldServerProps.setProperty("rhq.storage.password", "1eeb2f255e832171df8592078de921bc"); } String storageSeeds = oldServerProps.getProperty("rhq.cassandra.seeds"); if (storageSeeds != null) { StringBuffer storageNodes = new StringBuffer(); String cqlPort = ""; String[] unparsedNodes = storageSeeds.split(","); for (int index = 0; index < unparsedNodes.length; index++) { String[] params = unparsedNodes[index].split("\\|"); if (params.length == 3) { storageNodes.append(params[0]); if (index < unparsedNodes.length - 1) { storageNodes.append(","); } cqlPort = params[2]; } } oldServerProps.remove("rhq.cassandra.seeds"); oldServerProps.setProperty("rhq.storage.nodes", storageNodes.toString()); oldServerProps.setProperty("rhq.storage.cql-port", cqlPort); } String storageCompression = oldServerProps.getProperty("rhq.cassandra.client.compression-enabled"); if (storageCompression != null) { oldServerProps.remove("rhq.cassandra.client.compression-enabled"); oldServerProps.setProperty("rhq.storage.client.compression-enabled", storageCompression); } // copy the old key/truststore files from the old location to the new server configuration directory copyReferredFile(commandLine, oldServerProps, "rhq.server.tomcat.security.keystore.file"); copyReferredFile(commandLine, oldServerProps, "rhq.server.tomcat.security.truststore.file"); copyReferredFile(commandLine, oldServerProps, "rhq.communications.connector.security.keystore.file"); copyReferredFile(commandLine, oldServerProps, "rhq.communications.connector.security.truststore.file"); copyReferredFile(commandLine, oldServerProps, "rhq.server.client.security.keystore.file"); copyReferredFile(commandLine, oldServerProps, "rhq.server.client.security.truststore.file"); // for oracle, ensure the unused properties are set to unused, otherwise prop file validation may fail String dbType = oldServerProps.getProperty("rhq.server.database.type-mapping"); if (null != dbType && dbType.toLowerCase().contains("oracle")) { oldServerProps.setProperty("rhq.server.database.server-name", "unused"); oldServerProps.setProperty("rhq.server.database.port", "unused"); oldServerProps.setProperty("rhq.server.database.db-name", "unused"); } migrateRestrictedProperties(oldServerProps); // now merge the old settings in with the default properties from the new server install String newServerPropsFilePath = getServerPropertiesFile().getAbsolutePath(); PropertiesFileUpdate newServerPropsFile = new PropertiesFileUpdate(newServerPropsFilePath); newServerPropsFile.update(oldServerProps); return; } /** * Given server properties and a property name whose value is a file path, see if we need to copy the referred * file to the new server location. This will set the new property value in the given properties if it needed to be * updated. * * @param commandLine the rhqctl command line * @param properties the properties * @param propertyName name of a property whose value refers to a file path */ private void copyReferredFile(CommandLine commandLine, Properties properties, String propertyName) { String propertyValue = properties.getProperty(propertyName); if (propertyValue == null || propertyValue.trim().length() == 0) { return; } File referredFile = new File(propertyValue); boolean originalFilePathIsAbsolute = referredFile.isAbsolute(); if (!originalFilePathIsAbsolute) { // If its not absolute, we assume it is using some default syntax used in earlier versions // and we will know this if the value starts with one of the following: // ${jboss.server.config.dir} // ${jboss.server.home.dir}/conf // conf/ // All of which refer to the old server's configuration directory. File oldServerConfigDir = new File(getFromServerDir(commandLine), "jbossas/standalone/configuration"); if (!oldServerConfigDir.isDirectory()) { // the older RHQ releases had the old JBossAS 4.2.3 directory structure oldServerConfigDir = new File(getFromServerDir(commandLine), "jbossas/server/default/conf"); if (!oldServerConfigDir.isDirectory()) { log.warn("Cannot determine the old server's configuration directory - cannot copy over the old file: " + referredFile); return; } } String absPath = propertyValue.replace("${jboss.server.config.dir}", oldServerConfigDir.getAbsolutePath()); absPath = absPath.replace("${jboss.server.home.dir}/conf", useForwardSlash(oldServerConfigDir.getAbsolutePath())); if (absPath.startsWith("conf/")) { absPath = absPath.replaceFirst("conf", useForwardSlash(oldServerConfigDir.getAbsolutePath())); } referredFile = new File(absPath); } if (!referredFile.isFile()) { log.info("Server property [" + propertyName + "] refers to file [" + referredFile + "] that does not exist. Skipping."); return; } File newServerConfigDir = new File(getBaseDir(), "jbossas/standalone/configuration"); File newFile = new File(newServerConfigDir, referredFile.getName()); try { FileUtil.copyFile(referredFile, newFile); } catch (Exception e) { // log a message about this problem, but we will let the upgrade continue log.error("Failed to copy the old file [" + referredFile + "] referred to by server property [" + propertyName + "] to the new location of [" + newFile + "]. You will need to manually copy that file to the new location." + "The server may not work properly until you do this."); } properties.setProperty(propertyName, "${jboss.server.config.dir}/" + newFile.getName()); return; } private String useForwardSlash(String path) { return (null != path) ? path.replace('\\', '/') : null; } private int upgradeAgent(CommandLine rhqctlCommandLine) throws Exception { try { File oldAgentDir; if (rhqctlCommandLine.hasOption(FROM_AGENT_DIR_OPTION)) { oldAgentDir = new File(rhqctlCommandLine.getOptionValue(FROM_AGENT_DIR_OPTION)); if (!oldAgentDir.isDirectory()) { throw new FileNotFoundException("Missing agent to upgrade: " + oldAgentDir.getAbsolutePath()); } } else { oldAgentDir = null; File fromServerDir = getFromServerDir(rhqctlCommandLine); if (fromServerDir != null && fromServerDir.isDirectory()) { File fromServerDirParent = fromServerDir.getParentFile(); if (fromServerDirParent != null && fromServerDirParent.isDirectory()) { oldAgentDir = new File(fromServerDirParent, "rhq-agent"); } } if (!oldAgentDir.isDirectory()) { log.info("No " + FROM_AGENT_DIR_OPTION + " option specified and no agent found in the default location [" + oldAgentDir.getAbsolutePath() + "]. Installing agent in the default location as part of the upgrade."); return installAgent(getAgentBasedir(), rhqctlCommandLine); } } log.info("Upgrading RHQ agent located at: " + oldAgentDir.getAbsolutePath()); final File agentBasedir = getAgentBasedir(); File agentInstallerJar = getFileDownload("rhq-agent", "rhq-enterprise-agent"); int exitValue = updateAndMoveExistingAgent(agentBasedir, oldAgentDir, agentInstallerJar); addUndoTask(new ControlCommand.UndoTask("Removing agent install directory") { public void performUndoWork() { FileUtil.purge(agentBasedir, true); } }); log.info("The agent has been upgraded and placed in: " + agentBasedir); return exitValue; } catch (IOException e) { log.error("An error occurred while upgrading the agent: " + e.getMessage()); throw e; } } /** * Migrates default restricted properties to the correct restricted/obfuscated format. * * @param properties properties to migrate */ private void migrateRestrictedProperties(Properties properties) { List defaultRestrictedProperties = new ArrayList(); defaultRestrictedProperties.add("rhq.server.client.security.keystore.password"); defaultRestrictedProperties.add("rhq.server.client.security.keystore.key-password"); defaultRestrictedProperties.add("rhq.server.client.security.truststore.password"); defaultRestrictedProperties.add("rhq.communications.connector.security.keystore.key-password"); defaultRestrictedProperties.add("rhq.communications.connector.security.keystore.password"); defaultRestrictedProperties.add("rhq.communications.connector.security.truststore.password"); defaultRestrictedProperties.add("rhq.server.tomcat.security.keystore.password"); defaultRestrictedProperties.add("rhq.server.tomcat.security.keystore.key-password"); defaultRestrictedProperties.add("rhq.server.tomcat.security.truststore.password"); for (String restrictedProperty : defaultRestrictedProperties) { String value = (String) properties.get(restrictedProperty); if (value == null) { continue; } try { if (RestrictedFormat.isRestrictedFormat(value)) { value = RestrictedFormat.retrieveValue(value); PicketBoxObfuscator.decode(value); } else { throw new Exception("Value not in a restricted format"); } } catch (Exception ex) { properties.put(restrictedProperty, RestrictedFormat.formatValue(PicketBoxObfuscator.encode(value))); } } } private List validateOptions(CommandLine commandLine) { List errors = new LinkedList(); // When updating storage cluster schema everything else is ignored if (commandLine.hasOption(STORAGE_SCHEMA_OPTION) || commandLine.hasOption(LIST_VERSIONS_OPTION)) { return errors; } if (!commandLine.hasOption(FROM_SERVER_DIR_OPTION)) { errors.add("Missing required option: " + FROM_SERVER_DIR_OPTION); } else { File fromServerDir = new File(commandLine.getOptionValue(FROM_SERVER_DIR_OPTION)); if (!fromServerDir.isDirectory()) { errors.add("The " + FROM_SERVER_DIR_OPTION + " directory does not exist: [" + fromServerDir.getPath() + "]"); } else { File serverPropsFile = new File(fromServerDir, "bin/rhq-server.properties"); if (!serverPropsFile.isFile()) { errors.add("The " + FROM_SERVER_DIR_OPTION + " directory does not appear to be an RHQ installation. Missing expected file: [" + serverPropsFile.getPath() + "]"); } } } if (isRhq48OrLater(commandLine)) { if (commandLine.hasOption(STORAGE_DATA_ROOT_DIR)) { errors.add("The option --" + STORAGE_DATA_ROOT_DIR + " is valid only for upgrades from older systems that did not have storage nodes."); } } if (commandLine.hasOption(FROM_AGENT_DIR_OPTION)) { File fromAgentDir = new File(commandLine.getOptionValue(FROM_AGENT_DIR_OPTION)); if (!fromAgentDir.isDirectory()) { errors.add("The " + FROM_AGENT_DIR_OPTION + " directory does not exist: [" + fromAgentDir.getPath() + "]"); } else { String agentEnvFileName = (File.separatorChar == '/') ? "bin/rhq-agent-env.sh" : "bin/rhq-agent-env.bat"; File agentEnvFile = new File(fromAgentDir, agentEnvFileName); if (!agentEnvFile.isFile()) { errors.add("The " + FROM_AGENT_DIR_OPTION + " directory does not appear to be an RHQ Agent installation. Missing expected file: [" + agentEnvFile.getPath() + "]"); } } } return errors; } static public File getFromServerDir(CommandLine commandLine) { return (commandLine.hasOption(FROM_SERVER_DIR_OPTION)) ? new File( commandLine.getOptionValue(FROM_SERVER_DIR_OPTION)) : null; } protected boolean isRhq48OrLater(CommandLine commandLine) { return new File(getFromServerDir(commandLine), "bin/rhqctl").exists(); } protected boolean isRhq410OrLater(CommandLine commandLine) { return new File(getFromServerDir(commandLine), "bin/internal").isDirectory(); } private int updateStorageSchema(CommandLine commandLine) { // Only performed from a server install if (!isServerInstalled()) { log.info("This command can only be performed from an installed Server node. This is either a standalone Storage Node, or the Server has yet to be installed."); return RHQControl.EXIT_CODE_OPERATION_FAILED; } int rValue = RHQControl.EXIT_CODE_OK; try { Future integerFuture = runRHQServerInstaller(ServerInstallerAction.UPDATESTORAGESCHEMA); rValue = Math.max(rValue, integerFuture.get()); } catch (Exception e) { log.error("Updating the RHQ Storage Cluster schema failed: " + e.getMessage()); rValue = RHQControl.EXIT_CODE_OPERATION_FAILED; } return rValue; } private int listVersions(CommandLine commandLine) { // Only performed from a server install if (!isServerInstalled()) { log.info("This command can only be performed from an installed Server node. This is either a standalone Storage Node, or the Server has yet to be installed."); return RHQControl.EXIT_CODE_OPERATION_FAILED; } int rValue = RHQControl.EXIT_CODE_OK; try { Future integerFuture = runRHQServerInstaller(ServerInstallerAction.LISTVERSIONS); //waitForRHQServerToInitialize(integerFuture); rValue = Math.max(rValue, integerFuture.get()); } catch (Exception e) { log.error("Reporting topology status failed: " + e.getMessage()); rValue = RHQControl.EXIT_CODE_OPERATION_FAILED; } return rValue; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy