com.clustercontrol.notify.util.ExecCommand.java Source code

Java tutorial

Introduction

Here is the source code for com.clustercontrol.notify.util.ExecCommand.java

Source

/*
    
Copyright (C) 2009 NTT DATA Corporation
    
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.
    
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.
    
 */

package com.clustercontrol.notify.util;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.clustercontrol.bean.HinemosModuleConstant;
import com.clustercontrol.bean.PriorityConstant;
import com.clustercontrol.commons.util.MonitoredThreadPoolExecutor;
import com.clustercontrol.fault.HinemosUnknown;
import com.clustercontrol.fault.NotifyNotFound;
import com.clustercontrol.maintenance.util.HinemosPropertyUtil;
import com.clustercontrol.notify.bean.NotifyRequestMessage;
import com.clustercontrol.notify.bean.OutputBasicInfo;
import com.clustercontrol.notify.model.NotifyCommandInfo;
import com.clustercontrol.util.CommandCreator;
import com.clustercontrol.util.CommandExecutor;
import com.clustercontrol.util.CommandExecutor.CommandResult;
import com.clustercontrol.util.MessageConstant;
import com.clustercontrol.util.StringBinder;
import com.clustercontrol.util.apllog.AplLogger;

/**
 * ?<BR>
 *
 * @version 3.0.0
 * @since 3.0.0
 */
public class ExecCommand implements Notifier {
    /** ? */
    private static Log m_log = LogFactory.getLog(ExecCommand.class);

    private static final String THREAD_POOL_COUNT_KEY = "notify.command.thread.pool.count";
    private static final int THREAD_POOL_COUNT_DEFAULT = 8;

    private static final String COMMAND_CREATE_MODE = "notify.command.create.mode";
    private static final String COMMAND_SUCCESS_EXIT = "notify.command.success.exit";
    private static final int COMMAND_SUCCESS_EXIT_DEFAULT = 0;

    // ?????2?Executor????
    // 1.?CommandTask??Executor
    //   ????
    // 2.?CommandTask?Executor
    //   ????????

    // ?CommandTask???????CommandCallerTask?
    // ???ExecutorService
    private static ExecutorService _callerExecutorService;

    static {
        // hinemos.properties???
        int threadPoolCount = HinemosPropertyUtil
                .getHinemosPropertyNum(THREAD_POOL_COUNT_KEY, Long.valueOf(THREAD_POOL_COUNT_DEFAULT)).intValue();

        _callerExecutorService = new MonitoredThreadPoolExecutor(threadPoolCount, threadPoolCount, 0L,
                TimeUnit.MICROSECONDS, new LinkedBlockingQueue<Runnable>(), new CommandTaskThreadFactory());
    }

    /**
     * ?????
     *
     * @param outputInfo 
     * @throws NotifyNotFound
     * @throws HinemosUnknown
     */
    @Override
    public synchronized void notify(NotifyRequestMessage message) throws NotifyNotFound, HinemosUnknown {
        if (m_log.isDebugEnabled()) {
            m_log.debug("notify() " + message);
        }

        executeCommand(message.getOutputInfo(), message.getNotifyId());
    }

    // ??
    private String getCommandString(OutputBasicInfo outputInfo, NotifyCommandInfo commandInfo, int priority) {
        // ??
        try {
            Map<String, String> param = NotifyUtil.createParameter(outputInfo, commandInfo.getNotifyInfoEntity());
            StringBinder binder = new StringBinder(param);
            return binder.bindParam(getCommand(commandInfo, priority));
        } catch (Exception e) {
            m_log.warn("notify() : " + e.getClass().getSimpleName() + ", " + e.getMessage(), e);

            // ??????????
            return getCommand(commandInfo, priority);
        }
    }

    private String getCommand(NotifyCommandInfo commandInfo, int priority) {
        switch (priority) {
        case PriorityConstant.TYPE_INFO:
            return commandInfo.getInfoCommand();
        case PriorityConstant.TYPE_WARNING:
            return commandInfo.getWarnCommand();
        case PriorityConstant.TYPE_CRITICAL:
            return commandInfo.getCriticalCommand();
        case PriorityConstant.TYPE_UNKNOWN:
            return commandInfo.getUnknownCommand();

        default:
            break;
        }
        return null;
    }

    /**
     * ?????
     *
     * @param outputInfo 
     */
    private synchronized void executeCommand(OutputBasicInfo outputInfo, String notifyId) {
        if (m_log.isDebugEnabled()) {
            m_log.debug("executeCommand() " + outputInfo);
        }

        NotifyCommandInfo commandInfo;
        try {
            commandInfo = QueryUtil.getNotifyCommandInfoPK(notifyId);

            // commandInfo.getCommand()??command????????
            // commandInfo.getCommand()??????
            // TextReplacer????
            // command?????
            String command = getCommandString(outputInfo, commandInfo, outputInfo.getPriority());

            /**
             * 
             */
            // ???
            String sysUserName = System.getProperty("user.name");
            String effectiveUser = getEffectiveUser(commandInfo, outputInfo.getPriority());
            boolean setEnvFlag;
            if (commandInfo.getSetEnvironment().booleanValue()) {
                setEnvFlag = true;
            } else {
                setEnvFlag = false;
            }
            long commadTimeout = commandInfo.getTimeout();

            // Hinemos Manager??root????
            // ?????????
            if ((!sysUserName.equals("root")) && (!sysUserName.equals(effectiveUser))) {
                // 
                String detailMsg = "The execution user of the command and hinemos manager's user are different.";
                m_log.info(detailMsg);
                internalErrorNotify(PriorityConstant.TYPE_CRITICAL, notifyId,
                        MessageConstant.MESSAGE_SYS_007_NOTIFY, detailMsg);
                return;
            } else {
                m_log.debug("NotifyCommand Submit : " + outputInfo + " command=" + command);

                // ?
                Future<Long> ret = _callerExecutorService.submit(new CommandCallerTask(effectiveUser, command,
                        setEnvFlag, notifyId, outputInfo, commadTimeout));

                if (ret.isCancelled())
                    m_log.debug("Cancelled NotifyCommand Submit : " + outputInfo + " command=" + command);
            }
        } catch (NotifyNotFound e) {
            String detailMsg = e.getMessage();
            m_log.info(
                    "executeCommand() " + detailMsg + " : " + e.getClass().getSimpleName() + ", " + e.getMessage());
            internalErrorNotify(PriorityConstant.TYPE_CRITICAL, notifyId, MessageConstant.MESSAGE_SYS_007_NOTIFY,
                    detailMsg);
        }
    }

    private String getEffectiveUser(NotifyCommandInfo commandInfo, int priority) {
        switch (priority) {
        case PriorityConstant.TYPE_INFO:
            return commandInfo.getInfoEffectiveUser();
        case PriorityConstant.TYPE_WARNING:
            return commandInfo.getWarnEffectiveUser();
        case PriorityConstant.TYPE_CRITICAL:
            return commandInfo.getCriticalEffectiveUser();
        case PriorityConstant.TYPE_UNKNOWN:
            return commandInfo.getUnknownEffectiveUser();

        default:
            break;
        }
        return null;
    }

    // ?????
    class CommandCallerTask implements Callable<Long> {
        // 
        private final String _effectiveUser;

        // ?
        private final String _execCommand;

        private final String _notifyId;

        private final long _commadTimeout;

        public CommandCallerTask(String effectiveUser, String execCommand, boolean setEnvFlag, String notifyId,
                OutputBasicInfo outputInfo, long commadTimeout) {
            _effectiveUser = effectiveUser;
            _execCommand = execCommand;
            _notifyId = notifyId;
            _commadTimeout = commadTimeout;
        }

        /**
         * CommandTask???????????????
         */
        @Override
        public Long call() throws Exception {
            // ??????????????????
            long returnValue = Long.MIN_VALUE;

            // ????
            String _mode = HinemosPropertyUtil.getHinemosPropertyStr(COMMAND_CREATE_MODE, "auto");
            CommandCreator.PlatformType _modeType = CommandCreator.convertPlatform(_mode);

            // ?
            String[] cmd = CommandCreator.createCommand(_effectiveUser, _execCommand, _modeType);

            m_log.info("call() excuting command. (effectiveUser = " + _effectiveUser + ", command = " + _execCommand
                    + ", mode = " + _modeType + ", timeout = " + _commadTimeout + ")");

            // ??
            CommandExecutor cmdExec = new CommandExecutor(cmd, _commadTimeout);
            cmdExec.execute();
            CommandResult ret = cmdExec.getResult();

            if (ret != null) {
                m_log.info("call() executed command. (exitCode = " + ret.exitCode + ", stdout = " + ret.stdout
                        + ", stderr = " + ret.stderr + ")");
            }

            if (ret == null || ret.exitCode == null) {
                internalErrorNotify(PriorityConstant.TYPE_CRITICAL, _notifyId,
                        MessageConstant.MESSAGE_SYS_007_NOTIFY,
                        "command execution failure (timeout). [command = " + _execCommand + "]");
            } else {
                returnValue = ret.exitCode;
                // ???DB???
                int _successExitCode = HinemosPropertyUtil
                        .getHinemosPropertyNum(COMMAND_SUCCESS_EXIT, Long.valueOf(COMMAND_SUCCESS_EXIT_DEFAULT))
                        .intValue();

                if (returnValue != _successExitCode) {
                    internalErrorNotify(PriorityConstant.TYPE_CRITICAL, _notifyId,
                            MessageConstant.MESSAGE_SYS_007_NOTIFY,
                            "command execution failure. [command = " + _execCommand + ", exit code = " + returnValue
                                    + ", stdout = " + ret.stdout + ", stderr = " + ret.stderr + "]");
                }
            }

            return returnValue;
        }
    }

    // CommandTask????????Factory
    private static class CommandTaskThreadFactory implements ThreadFactory {
        private volatile int _count = 0;

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "NotifyCommandTask-" + _count++);
        }
    }

    /**
     * ????
     */
    @Override
    public void internalErrorNotify(int priority, String notifyId, MessageConstant msgCode, String detailMsg) {
        String[] args = { notifyId };
        // 
        AplLogger.put(priority, HinemosModuleConstant.PLATFORM_NOTIFY, msgCode, args, detailMsg);
    }
}