/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ngrinder; import com.beust.jcommander.JCommander; import net.grinder.AgentControllerDaemon; import net.grinder.util.VersionNumber; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.hyperic.sigar.ProcState; import org.hyperic.sigar.Sigar; import org.hyperic.sigar.SigarException; import org.ngrinder.common.constants.AgentConstants; import org.ngrinder.common.constants.CommonConstants; import org.ngrinder.infra.AgentConfig; import org.ngrinder.infra.ArchLoaderInit; import org.ngrinder.monitor.agent.MonitorServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Properties; import static net.grinder.util.NetworkUtils.getIP; import static org.ngrinder.common.constants.InternalConstants.PROP_INTERNAL_NGRINDER_VERSION; import static org.ngrinder.common.util.NoOp.noOp; /** * Main class to start agent or monitor. * * @author Mavlarn * @author JunHo Yoon * @since 3.0 */ public class NGrinderAgentStarter implements AgentConstants, CommonConstants { private static final Logger LOG = LoggerFactory.getLogger("starter"); private AgentConfig agentConfig; private AgentControllerDaemon agentController; /** * Constructor. */ public NGrinderAgentStarter() { } public void init() { // Check agent start mode this.agentConfig = createAgentConfig(); try { new ArchLoaderInit().init(agentConfig.getHome().getNativeDirectory()); } catch (Exception e) { LOG.error("Error while expanding native lib", e); } } protected AgentConfig createAgentConfig() { AgentConfig agentConfig = new AgentConfig(); agentConfig.init(); return agentConfig; } /* * Get the start mode, "agent" or "monitor". If it is not set in configuration, it will return "agent". */ public String getStartMode() { return agentConfig.getCommonProperties().getProperty(PROP_COMMON_START_MODE); } /** * Get agent version. * * @return version string */ public String getVersion() { return agentConfig.getInternalProperties().getProperty(PROP_INTERNAL_NGRINDER_VERSION); } /** * Start the performance monitor. */ public void startMonitor() { printLog("***************************************************"); printLog("* Start nGrinder Monitor... "); printLog("***************************************************"); try { MonitorServer.getInstance().init(agentConfig); MonitorServer.getInstance().start(); } catch (Exception e) { LOG.error("ERROR: {}", e.getMessage()); printHelpAndExit("Error while starting Monitor", e); } } /** * Stop monitors. * Only for unit-test. */ void stopMonitor() { MonitorServer.getInstance().stop(); } /** * Start ngrinder agent. */ public void startAgent() { printLog("***************************************************"); printLog(" Start nGrinder Agent ..."); printLog("***************************************************"); if (StringUtils.isEmpty(System.getenv("JAVA_HOME"))) { printLog("Hey!! JAVA_HOME env var was not provided. " + "Please provide JAVA_HOME env var before running agent." + "Otherwise you can not execute the agent in the security mode."); } boolean serverMode = agentConfig.isServerMode(); if (!serverMode) { printLog("JVM server mode is disabled."); } String controllerIP = getIP(agentConfig.getControllerIP()); int controllerPort = agentConfig.getControllerPort(); agentConfig.setControllerHost(controllerIP); LOG.info("connecting to controller {}:{}", controllerIP, controllerPort); try { agentController = new AgentControllerDaemon(agentConfig); agentController.run(); } catch (Exception e) { LOG.error("Error while connecting to : {}:{}", controllerIP, controllerPort); printHelpAndExit("Error while starting Agent", e); } } private void printLog(String s, Object... args) { if (!agentConfig.isSilentMode()) { LOG.info(s, args); } } /** * Stop the ngrinder agent. * Only for unit-test. */ void stopAgent() { LOG.info("Stop nGrinder agent!"); agentController.shutdown(); } public static NGrinderAgentStarterParam.NGrinderModeParam modeParam; /** * Agent starter. * * @param args arguments */ public static void main(String[] args) { NGrinderAgentStarter starter = new NGrinderAgentStarter(); final NGrinderAgentStarterParam param = new NGrinderAgentStarterParam(); checkJavaVersion(); JCommander commander = new JCommander(param); commander.setProgramName("ngrinder-agent"); commander.setAcceptUnknownOptions(true); try { commander.parse(args); } catch (Exception e) { LOG.error(e.getMessage()); return; } final List<String> unknownOptions = commander.getUnknownOptions(); modeParam = param.getModeParam(); modeParam.parse(unknownOptions.toArray(new String[unknownOptions.size()])); if (modeParam.version != null) { System.out.println("nGrinder v" + getStaticVersion()); return; } if (modeParam.help != null) { modeParam.usage(); return; } System.getProperties().putAll(modeParam.params); starter.init(); final String startMode = modeParam.name(); if ("stop".equalsIgnoreCase(param.command)) { starter.stopProcess(startMode); System.out.println("Stop the " + startMode); return; } starter.checkDuplicatedRun(startMode); if (startMode.equalsIgnoreCase("agent")) { starter.startAgent(); } else if (startMode.equalsIgnoreCase("monitor")) { starter.startMonitor(); } else { staticPrintHelpAndExit("Invalid agent.conf, '--mode' must be set as 'monitor' or 'agent'."); } } private static String getStaticVersion() { InputStream inputStream = null; Properties properties = new Properties(); try { inputStream = NGrinderAgentStarter.class.getResourceAsStream("/internal.properties"); properties.load(inputStream); } catch (IOException e) { // Do nothing. } finally { IOUtils.closeQuietly(inputStream); } return properties.getProperty("ngrinder.version", "UNKNOWN"); } static void checkJavaVersion() { String curJavaVersion = System.getProperty("java.version", "1.6"); checkJavaVersion(curJavaVersion); } static void checkJavaVersion(String curJavaVersion) { if (new VersionNumber(curJavaVersion).compareTo(new VersionNumber("1.6")) < 0) { LOG.info("- Current java version {} is less than 1.6. nGrinder Agent might not work well", curJavaVersion); } } /** * Stop process. * * @param mode agent or monitor. */ protected void stopProcess(String mode) { String pid = agentConfig.getAgentPidProperties(mode); try { if (StringUtils.isNotBlank(pid)) { new Sigar().kill(pid, 15); } agentConfig.updateAgentPidProperties(mode); } catch (SigarException e) { printHelpAndExit(String.format("Error occurred while terminating %s process.\n" + "It can be already stopped or you may not have the permission.\n" + "If everything is OK. Please stop it manually.", mode), e); } } /** * Check if the process is already running in this env. * * @param startMode monitor or agent */ public void checkDuplicatedRun(String startMode) { Sigar sigar = new Sigar(); String existingPid = this.agentConfig.getAgentPidProperties(startMode); if (StringUtils.isNotEmpty(existingPid)) { try { ProcState procState = sigar.getProcState(existingPid); if (procState.getState() == ProcState.RUN || procState.getState() == ProcState.IDLE || procState.getState() == ProcState.SLEEP) { printHelpAndExit("Currently " + startMode + " is running with pid " + existingPid + ". Please stop it before run"); } agentConfig.updateAgentPidProperties(startMode); } catch (SigarException e) { noOp(); } } this.agentConfig.saveAgentPidProperties(String.valueOf(sigar.getPid()), startMode); } /** * Print help and exit. This is provided for mocking. * * @param message message */ protected void printHelpAndExit(String message) { staticPrintHelpAndExit(message); } /** * print help and exit. This is provided for mocking. * * @param message message * @param e exception */ protected void printHelpAndExit(String message, Exception e) { staticPrintHelpAndExit(message, e); } private static void staticPrintHelpAndExit(String message) { staticPrintHelpAndExit(message, null); } private static void staticPrintHelpAndExit(String message, Exception e) { if (e == null) { LOG.error(message); } else { LOG.error(message, e); } if (modeParam != null) { modeParam.usage(); } System.exit(-1); } }