Java tutorial
/* * RHQ Management Platform * Copyright (C) 2005-2011 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.modules.plugins.jbossas7; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.ConnectException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.sasl.util.UsernamePasswordHashUtil; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.measurement.MeasurementDataTrait; import org.rhq.core.domain.measurement.MeasurementReport; import org.rhq.core.domain.measurement.MeasurementScheduleRequest; import org.rhq.core.pluginapi.measurement.MeasurementFacet; import org.rhq.core.pluginapi.operation.OperationResult; import org.rhq.core.pluginapi.util.ProcessExecutionUtility; import org.rhq.core.system.ProcessExecution; import org.rhq.core.system.ProcessExecutionResults; import org.rhq.modules.plugins.jbossas7.json.Address; import org.rhq.modules.plugins.jbossas7.json.Operation; import org.rhq.modules.plugins.jbossas7.json.ReadAttribute; import org.rhq.modules.plugins.jbossas7.json.Result; /** * Base component for functionality that is common to Standalone AS and HostControllers * @author Heiko W. Rupp */ public class BaseServerComponent extends BaseComponent implements MeasurementFacet { private static final String SEPARATOR = "\n-----------------------\n"; final Log log = LogFactory.getLog(BaseServerComponent.class); /** * Restart the server by first executing a 'shutdown' operation via its API. Then call * the #startServer method to start it again. * * @param parameters Parameters to pass to the (recursive) invocation of #invokeOperation * @param mode Mode of the server to start (domain or standalone) * @return State of execution * @throws Exception If anything goes wrong */ protected OperationResult restartServer(Configuration parameters, AS7Mode mode) throws Exception { OperationResult tmp = invokeOperation("shutdown", parameters); if (tmp.getErrorMessage() != null) { tmp.setErrorMessage("Restart failed while failing to shut down: " + tmp.getErrorMessage()); return tmp; } boolean down = false; int count = 0; while (!down) { count++; Thread.sleep(1000); // Wait 1s Operation op = new ReadAttribute(new Address(), "release-version"); Result res = getASConnection().execute(op); if (!res.isSuccess()) { // If op succeeds, server is not down down = true; } if (count > 20) { tmp.setErrorMessage("Was not able to shut down the server"); return tmp; } } return startServer(mode); } /** * Start the server by calling the start script listed in the plugin configuration. If a different * config is given, this is passed via --server-config * @return State of Execution. * @param mode Mode of the server to start (domain or standalone) */ protected OperationResult startServer(AS7Mode mode) { OperationResult operationResult = new OperationResult(); String startScript = pluginConfiguration.getSimpleValue("startScript", mode.getStartScript()); String baseDir = pluginConfiguration.getSimpleValue("baseDir", ""); if (baseDir.isEmpty()) { operationResult.setErrorMessage("No base directory provided"); return operationResult; } String script = baseDir + File.separator + startScript; ProcessExecution processExecution; processExecution = ProcessExecutionUtility.createProcessExecution(new File("/bin/sh")); String config = pluginConfiguration.getSimpleValue(mode.getConfigPropertyName(), mode.getDefaultXmlFile()); List<String> arguments = processExecution.getArguments(); if (arguments == null) { arguments = new ArrayList<String>(); processExecution.setArguments(arguments); } arguments.add(script); if (!config.equals(mode.getDefaultXmlFile())) { arguments.add(mode.getConfigArg()); arguments.add(config); } if (mode == AS7Mode.DOMAIN) { // We also need to check for host-config config = pluginConfiguration.getSimpleValue(AS7Mode.HOST.getConfigPropertyName(), AS7Mode.HOST.getDefaultXmlFile()); if (!config.equals(AS7Mode.HOST.getDefaultXmlFile())) { arguments.add(AS7Mode.HOST.getConfigArg()); arguments.add(config); } } processExecution.setWorkingDirectory(baseDir); processExecution.setCaptureOutput(true); processExecution.setWaitForCompletion(15000L); // 15 seconds // TODO: Should we wait longer than 15 seconds? processExecution.setKillOnTimeout(false); String javaHomeDir = pluginConfiguration.getSimpleValue("javaHomePath", null); if (javaHomeDir != null) { processExecution.getEnvironmentVariables().put("JAVA_HOME", javaHomeDir); } if (log.isDebugEnabled()) { log.debug("About to execute the following process: [" + processExecution + "]"); } ProcessExecutionResults results = context.getSystemInformation().executeProcess(processExecution); logExecutionResults(results); if (results.getError() != null) { operationResult.setErrorMessage(results.getError().getMessage()); } else if (results.getExitCode() != null) { operationResult.setErrorMessage( "Start failed with error code " + results.getExitCode() + ":\n" + results.getCapturedOutput()); } else { operationResult.setSimpleResult("Success"); } return operationResult; } private void logExecutionResults(ProcessExecutionResults results) { // Always log the output at info level. On Unix we could switch depending on a exitCode being !=0, but ... log.info("Exit code from process execution: " + results.getExitCode()); log.info("Output from process execution: " + SEPARATOR + results.getCapturedOutput() + SEPARATOR); } /** * Do some post processing of the Result - especially the 'shutdown' operation needs a special * treatment. * @param name Name of the operation * @param res Result of the operation vs. AS7 * @return OperationResult filled in from values of res */ protected OperationResult postProcessResult(String name, Result res) { OperationResult operationResult = new OperationResult(); if (res == null) { operationResult.setErrorMessage("No result received from server"); return operationResult; } if (name.equals("shutdown") || name.equals("reload")) { /* * Shutdown needs a special treatment, because after sending the operation, if shutdown succeeds, * the server connection is closed and we can't read from it. So if we get connection refused for * reading, this is a good sign. */ if (!res.isSuccess()) { if (res.getRhqThrowable() != null && (res.getRhqThrowable() instanceof ConnectException || res.getRhqThrowable().getMessage().equals("Connection refused"))) { operationResult.setSimpleResult("Success"); log.debug("Got a ConnectionRefused for operation " + name + " this is considered ok, as the remote server sometimes closes the communications channel before sending a reply"); } if (res.getFailureDescription().contains("Socket closed")) { // See https://issues.jboss.org/browse/AS7-4192 operationResult.setSimpleResult("Success"); log.debug("Got a 'Socket closed' result from AS for operation " + name); } else operationResult.setErrorMessage(res.getFailureDescription()); } else { operationResult.setSimpleResult("Success"); } } else { if (res.isSuccess()) { if (res.getResult() != null) operationResult.setSimpleResult(res.getResult().toString()); else operationResult.setSimpleResult("-None provided by server-"); } else operationResult.setErrorMessage(res.getFailureDescription()); } return operationResult; } protected OperationResult installManagementUser(Configuration parameters, Configuration pluginConfig, AS7Mode mode) { String user = parameters.getSimpleValue("user", ""); String password = parameters.getSimpleValue("password", ""); OperationResult result = new OperationResult(); PropertySimple remoteProp = pluginConfig.getSimple("manuallyAdded"); if (remoteProp != null && remoteProp.getBooleanValue() != null && remoteProp.getBooleanValue()) { result.setErrorMessage( "This is a manually added server. This operation can not be used to install a management user. Use the server's 'bin/add-user.sh'"); return result; } if (user.isEmpty() || password.isEmpty()) { result.setErrorMessage("User and Password must not be empty"); return result; } String baseDir = pluginConfig.getSimpleValue("baseDir", ""); if (baseDir.isEmpty()) { result.setErrorMessage("No baseDir found, can not continue"); return result; } String standaloneXmlFile = pluginConfig.getSimpleValue("config", mode.getDefaultXmlFile()); String standaloneXml = baseDir + File.separator + mode.getBaseDir() + File.separator + "configuration" + File.separator + standaloneXmlFile; AbstractBaseDiscovery abd = new AbstractBaseDiscovery(); abd.readStandaloneOrHostXmlFromFile(standaloneXml); String realm = pluginConfig.getSimpleValue("realm", "ManagementRealm"); String propertiesFilePath = abd.getSecurityPropertyFileFromHostXml(baseDir, mode, realm); Properties p = new Properties(); try { UsernamePasswordHashUtil util = new UsernamePasswordHashUtil(); String value = util.generateHashedHexURP(user, realm, password.toCharArray()); FileInputStream fis = new FileInputStream(propertiesFilePath); p.load(fis); fis.close(); p.setProperty(user, value); FileOutputStream fos = new FileOutputStream(propertiesFilePath); p.store(fos, null); fos.flush(); fos.close(); } catch (IOException e) { log.error(e.getMessage()); result.setErrorMessage(e.getMessage()); } catch (NoSuchAlgorithmException nsae) { log.error(nsae.getMessage()); result.setErrorMessage(nsae.getMessage()); } result.setSimpleResult("User/Password set or updated"); log.info("Installed management user [" + user + "]."); return result; } public void getValues(MeasurementReport report, Set metrics) throws Exception { Set<MeasurementScheduleRequest> requests = metrics; Set<MeasurementScheduleRequest> leftovers = new HashSet<MeasurementScheduleRequest>(requests.size()); for (MeasurementScheduleRequest request : requests) { if (request.getName().equals("startTime")) { String path = getPath(); if (context.getResourceType().getName().contains("Host Controller")) { if (path != null) path = "host=master," + path; // TODO is the local controller always on host=master?? AS7-3678 else path = "host=master"; } Address address = new Address(path); address.add("core-service", "platform-mbean"); address.add("type", "runtime"); Operation op = new ReadAttribute(address, "start-time"); Result res = getASConnection().execute(op); if (res.isSuccess()) { Long startTime = (Long) res.getResult(); MeasurementDataTrait data = new MeasurementDataTrait(request, new Date(startTime).toString()); report.addData(data); } } else { leftovers.add(request); } } super.getValues(report, leftovers); } }