Package com.sun.enterprise.ee.admin.configbeans

Source Code of com.sun.enterprise.ee.admin.configbeans.NodeAgentsConfigBean

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package com.sun.enterprise.ee.admin.configbeans;

import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.NodeAgents;
import com.sun.enterprise.config.serverbeans.NodeAgent;
import com.sun.enterprise.config.serverbeans.Servers;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.JmxConnector;
import com.sun.enterprise.config.serverbeans.Ssl;
import com.sun.enterprise.config.serverbeans.AuthRealm;
import com.sun.enterprise.config.serverbeans.LogService;
import com.sun.enterprise.config.serverbeans.ModuleLogLevels;
import com.sun.enterprise.config.serverbeans.ElementProperty;
import com.sun.enterprise.config.serverbeans.ConfigAPIHelper;
import com.sun.enterprise.config.serverbeans.ServerHelper;
import com.sun.enterprise.config.serverbeans.NodeAgentHelper;

import com.sun.enterprise.config.ConfigException;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.config.ConfigException;
import com.sun.enterprise.admin.target.TargetType;
import com.sun.enterprise.admin.target.Target;
import com.sun.enterprise.admin.target.TargetBuilder;
import com.sun.enterprise.admin.common.Status;
import com.sun.enterprise.admin.util.IAdminConstants;
import com.sun.enterprise.admin.util.JMXConnectorConfig;

import com.sun.enterprise.util.i18n.StringManager;
import com.sun.enterprise.util.i18n.StringManagerBase;
import com.sun.enterprise.util.SystemPropertyConstants;

import com.sun.enterprise.ee.admin.servermgmt.AgentManager;
import com.sun.enterprise.ee.admin.servermgmt.AgentException;
import com.sun.enterprise.ee.admin.servermgmt.AgentConfig;
import com.sun.enterprise.admin.servermgmt.RuntimeStatus;
import com.sun.enterprise.admin.servermgmt.RuntimeStatusList;
import com.sun.enterprise.admin.servermgmt.KeystoreManager;

import com.sun.enterprise.ee.admin.mbeanapi.NodeAgentMBean;
import com.sun.enterprise.ee.admin.proxy.NodeAgentProxy;

import com.sun.enterprise.ee.admin.clientreg.NodeAgentRegistry;
import com.sun.enterprise.ee.admin.clientreg.InstanceRegistry;

import com.sun.logging.ee.EELogDomains;

import com.sun.enterprise.ee.admin.ExceptionHandler;

import com.sun.enterprise.admin.configbeans.BaseConfigBean;

import com.sun.enterprise.ee.admin.concurrent.Task;
import com.sun.enterprise.ee.admin.concurrent.Executor;

import java.util.logging.Logger;
import java.util.logging.Level;

/**
* <p>MBean class that facilitates the configuration of the NodeAgent for CLI and remote clients
*
*/

//ISSUE: Do we really want to throws an AgentException here as this will clients
//using this mbean to have our runtime; however we seem to be throwing our own
//exceptions everywhere else in the mbeans. The problem with MBeanException
//currently is that it masks the real exception (due to the fact that MBeanHelper
//does some bogus formatting on the exception.

public class NodeAgentsConfigBean extends BaseConfigBean implements IAdminConstants
{

    class GetRuntimeStatusTask extends Task {
        private static final long TIMEOUT_IN_MILLIS = 30000; //30 seconds
        private String _agentName;
        private RuntimeStatus _status;

        public GetRuntimeStatusTask(String agentName) {
            super(TIMEOUT_IN_MILLIS);
            _agentName = agentName;
            _status = new RuntimeStatus();
        }

        public RuntimeStatus getStatus() {
            return _status;
        }

        public void run() {
            try {
                _status = getRuntimeStatus(_agentName);
            } catch (AgentException ex) {
                StringManagerBase sm = StringManagerBase.getStringManager(
                    getLogger().getResourceBundleName());
                getLogger().log(Level.WARNING,
                    sm.getString("nodeagent.listNodeAgents.Exception", _agentName), ex);
                _status = new RuntimeStatus();
            }
        }
    }

    private static final StringManager _strMgr =
        StringManager.getManager(NodeAgentsConfigBean.class);

    private static Logger _logger = null;

    public NodeAgentsConfigBean(ConfigContext configContext) {
        super(configContext);
    }

    private static Logger getLogger()
    {
        if (_logger == null) {
            //We explicitly call EELogDomains.getLogger instead of Logger.getLogger()
            //so that our resource bundle will be properly initialized. This allows this
            //code to be invoked from something (i.e. in the case the CLI) which does not
            //have a custom log manager.
            _logger = EELogDomains.getLogger(EELogDomains.EE_ADMIN_LOGGER);
        }
        return _logger;
    }

    private static ExceptionHandler _handler = null;

    //The exception handler is used to parse and log exceptions
    protected static ExceptionHandler getExceptionHandler()
    {
        if (_handler == null) {
            _handler = new ExceptionHandler(getLogger());
        }
        return _handler;
    }

    public void clearRuntimeStatus(String agentName) throws AgentException
    {
        try {
            NodeAgentMBean agentMBean = NodeAgentProxy.getNodeAgentProxy(agentName);
            agentMBean.clearRuntimeStatus();
        } catch (Exception ex) {
            //Ignore any error indicating that the server is unreachable.
            //FIXTHIS: We could expect the proxy to do this for us as it
            //seems to be a common case.
            if (NodeAgentProxy.isUnreachable(ex)) {
                // do nothing
            } else {
                throw new AgentException(ex);
            }
        }
    }

    public RuntimeStatus getRuntimeStatus(String agentName) throws AgentException
    {
        try {
            NodeAgentMBean agentMBean = NodeAgentProxy.getNodeAgentProxy(agentName);
            return agentMBean.getRuntimeStatus();
        } catch (Exception ex) {
            //Ignore any error indicating that the server is unreachable.
            //FIXTHIS: We could expect the proxy to do this for us as it
            //seems to be a common case.
            if (NodeAgentProxy.isUnreachable(ex)) {
                return new RuntimeStatus(agentName);
            } else {
                throw new AgentException(ex);
            }
        }
    }

    public boolean isRunning(String agentName) throws AgentException
    {
        return getRuntimeStatus(agentName).isRunning();
    }
   
    /**
     * Fetches the runtime status of the given server instances in parallel.
     */
    public RuntimeStatusList getRuntimeStatus(NodeAgent[] agents)
    {
        GetRuntimeStatusTask[] tasks = new GetRuntimeStatusTask[agents.length];
        for (int i = 0; i < agents.length; i++) {
            tasks[i] = new GetRuntimeStatusTask(agents[i].getName());
        }
        Executor exec = new Executor(tasks);
        exec.run();
        RuntimeStatusList result = new RuntimeStatusList(agents.length);
        for (int i = 0; i < agents.length; i++) {
            result.add(tasks[i].getStatus());
        }
        return result;
    }

   
    public RuntimeStatusList getNodeAgentRuntimeStatus(String targetName) throws AgentException
    {
        final StringManager stringMgr = StringManager.getManager(AgentManager.class);
        try {
            final TargetType[] validTargets = {TargetType.NODE_AGENT, TargetType.CLUSTER,
                TargetType.DOMAIN, TargetType.SERVER};
            final ConfigContext configContext = getConfigContext();
            Target target = TargetBuilder.INSTANCE.createTarget(
                DOMAIN_TARGET, validTargets, targetName,
                configContext);
            final NodeAgent[] agents = target.getNodeAgents();         
                //Fetch the status of all the node agents in parallel
            return getRuntimeStatus(agents);           
        } catch (Exception ex) {
            throw getExceptionHandler().handleAgentException(
                ex, "nodeagent.listNodeAgents.Exception", targetName);
        }
    }
   
    /**
     * lists node agents and their status
     */
    public String[] listNodeAgentsAsString(String targetName, boolean andStatus) throws AgentException
    {
        final StringManager stringMgr = StringManager.getManager(AgentManager.class);
        try {
            final TargetType[] validTargets = {TargetType.NODE_AGENT, TargetType.CLUSTER,
                TargetType.DOMAIN, TargetType.SERVER};
            final ConfigContext configContext = getConfigContext();
            Target target = TargetBuilder.INSTANCE.createTarget(
                DOMAIN_TARGET, validTargets, targetName,
                configContext);
            final NodeAgent[] agents = target.getNodeAgents();
            final int numAgents = agents.length;
            String[] result = new String[numAgents];
            String nodeAgentName = null;
            RuntimeStatusList statusList = null;
            if (andStatus) {
                //Fetch the status of all the node agents in parallel
                statusList = getRuntimeStatus(agents);
            }
            for (int i = 0; i < numAgents; i++) {
                nodeAgentName = agents[i].getName();
                if (andStatus) {
                    result[i] = stringMgr.getString("listAgentElement", nodeAgentName,
                        (statusList.getStatus(i)).toShortString());
                } else {
                    result[i] = nodeAgentName;
                }
            }
            return result;
        } catch (Exception ex) {
            throw getExceptionHandler().handleAgentException(
                ex, "nodeagent.listNodeAgents.Exception", targetName);
        }
    }

    /**
     * Removes the specified node agent. This operation is triggered by the asadmin
     * delete-nodeagent-config command.
     */
    public void deleteNodeAgentConfig(String nodeAgentName) throws AgentException
    {
        try {
            final ConfigContext configContext = getConfigContext();
            //Get the node agent specified by nodeAgentName and ensure that it exists
            NodeAgent controller = NodeAgentHelper.getNodeAgentByName(configContext,
                nodeAgentName);

            //Ensure that there are no server instances referring to the node agent
            Server[] servers = ServerHelper.getServersOfANodeAgent(configContext,
                nodeAgentName);
            if (servers.length > 0) {
                throw new AgentException(_strMgr.getString("agentHasServerReferrences",
                    nodeAgentName, ServerHelper.getServersAsString(servers)));
            }

            //Get a connection to the agent's mbean server before removing the node controller;
            //otherwise, we may never be able to find it in domain.xml when we want to
            //synchronizeWithDAS below.
            try {
                NodeAgentRegistry.getNodeAgentConnection(nodeAgentName);
            } catch (Exception ex) {
                //The node agent may be unreachable (i.e. not listening) so this exception is expected.
                if (!NodeAgentRegistry.isMBeanServerUnreachable(ex)) {
                    throw new AgentException(ex);
                }
            }

            Domain domain = ConfigAPIHelper.getDomainConfigBean(configContext);
            NodeAgents controllers = domain.getNodeAgents();
            controllers.removeNodeAgent(controller, OVERWRITE);

            //Notify the Node Agent to rendezvous
            //FIXTHIS: We force persistence, clear any notifications, and update the
            //Application server's config context explicitely. Until this is modelled
            //as an event notification (TBD) we need this to happen before notifying or
            //the Node Agent will not synchronize the correct data.
            //QUESTION: What happens if an exception is thrown above (e.g. in addNodeAgent). How do
            //we restore the admin config context to its previous (and unpersisted value)???
            flushAll();

            //FIXTHIS: Currently we hard code the DAS info. The issues are
            //1) we need a system jmx-connector from the DAS from which to obtain host, port
            //and protocol. This is not yet re-integrated
            //2) we need a place to store the DAS authentication information -- new properties
            //in domain.xml

            NodeAgentMBean agentMBean = NodeAgentProxy.getNodeAgentProxy(nodeAgentName);
            agentMBean.synchronizeWithDAS();

            // clear the JMXConnectorRegistry cache, do not want to leave unused connections around
            NodeAgentRegistry.removeNodeAgentConnection(nodeAgentName);
        } catch (Exception ex) {
            throw getExceptionHandler().handleAgentException(
                ex, "nodeagent.unbindNodeAgent.Exception", nodeAgentName);
        }
    }


    /**
     * Adds the specified Node Agent to domain.xml. This operation is invoked by the asadmin
     * create-nodeagent-config command that updates domain.xml.
     */
    public void createNodeAgentConfig(String nodeAgentName) throws AgentException
    {
        // set defaults until domail.xml's dtd has been changed ???
        String host="localhost";
        String port="9999";
        try {
            final ConfigContext configContext = getConfigContext();
            //validate name uniqueness
            if (!ConfigAPIHelper.isNameUnique(configContext, nodeAgentName)) {
                 throw new AgentException(_strMgr.getString("agentNameNotUnique",
                    nodeAgentName));
            }

            //Get the node controller specified by nodeAgentName and ensure that it does not
            //already exist
            Domain domain = ServerBeansFactory.getDomainBean(configContext);
            NodeAgents controllers =domain.getNodeAgents();
            NodeAgent controller = controllers.getNodeAgentByName(nodeAgentName);
            if (controller != null) {
                throw new AgentException(_strMgr.getString("agentAlreadyExists", nodeAgentName));
            }

            // add in "0.0.0.0"  as use host as clientHostName has a place holder until CLI is decided ???
            addNodeAgent(AgentConfig.NODEAGENT_DEFAULT_HOST_ADDRESS, port, nodeAgentName,
                AgentConfig.NODEAGENT_JMX_DEFAULT_PROTOCOL, host, Boolean.FALSE);

        } catch (Exception ex) {
            throw getExceptionHandler().handleAgentException(
                ex, "nodeagent.bindNodeAgent.Exception", nodeAgentName);
        }
    }


    /**
     * Adds the specified Node Agent to the domain. This operation is invoked from
     * the Node Agent when it is initiating the rendezvous.
     */
    public String rendezvousWithDAS(String host, String port,
        String nodeAgentName, String protocol, String clientHostName) throws AgentException
    {
        String sxRet="";
        try {
            final ConfigContext configContext = getConfigContext();

            //Get the node controller specified by nodeAgentName and ensure that it does not
            //already exist
            Domain domain = ServerBeansFactory.getDomainBean(configContext);
            NodeAgents controllers =domain.getNodeAgents();
            NodeAgent controller = controllers.getNodeAgentByName(nodeAgentName);

            if (controller != null) {
               ElementProperty rendezvousProperty = controller.getElementPropertyByName(RENDEZVOUS_PROPERTY_NAME);
               String rendezvous=rendezvousProperty.getValue();
               if (rendezvous != null && rendezvousProperty.getValue().equals(Boolean.TRUE.toString())) {
                    // should only rendezvous once, not the same, throw exception
                    throw new AgentException(_strMgr.getString("agentAlreadyExists", nodeAgentName));
                }

                // alter node agent in domain.xml to the criteria sent
                alterNodeAgent(host, port, nodeAgentName, protocol, clientHostName, Boolean.TRUE);

            } else {
                // need to make sure a unique instance is being added.
                if (!ConfigAPIHelper.isNameUnique(configContext, nodeAgentName)) {
                     throw new AgentException(_strMgr.getString("agentNameNotUnique",
                        nodeAgentName));
                }

                // add node agent to domain.xml
                addNodeAgent(host, port, nodeAgentName, protocol, clientHostName, Boolean.TRUE);
            }

            // after proper nodeagent rendezvous, return port for system jmx connector
            String dasName = System.getProperty(SystemPropertyConstants.SERVER_NAME);
            if (dasName == null) {
                throw new AgentException(_strMgr.getString("noDASServerNameProperty"));
            }
           
            JmxConnector dasConnector=ServerHelper.getServerSystemConnector(configContext, dasName);
            //JMXConnectorConfig dasConnectorConfig = ServerHelper.getJMXConnectorInfo(configContext, dasName);
            getLogger().log(Level.FINE," Nodeagent: " + nodeAgentName + " has Renezvoused -  returning DAS JMXport|Security Enabled - " +
                dasConnector.getPort() + "|" + dasConnector.isSecurityEnabled());
            sxRet=dasConnector.getPort() + "|" + String.valueOf(dasConnector.isSecurityEnabled());

        } catch (Exception ex) {
            throw getExceptionHandler().handleAgentException(
                ex, "nodeagent.rendezvousWithDAS.Exception", nodeAgentName);
        }

        return sxRet;
    }


    protected void addNodeAgent(String host, String port,
        String nodeAgentName, String protocol, String clientHostName, Boolean rendezvousOccurred)
        throws AgentException
    {
        try {
            final ConfigContext configContext = getConfigContext();
            //Validate port number since it is a string...
            try {
                Integer.parseInt(port);
            } catch (NumberFormatException ex) {
                throw new AgentException(_strMgr.getString("portMustBeNumeric",
                    port));
            }

            NodeAgents controllers = ServerBeansFactory.getDomainBean(configContext).getNodeAgents();

            //Create the new node controller
            NodeAgent controller = new NodeAgent();
            controller.setName(nodeAgentName);

            ElementProperty rendezvousProperty = new ElementProperty();
            rendezvousProperty.setName(RENDEZVOUS_PROPERTY_NAME);
            rendezvousProperty.setValue(rendezvousOccurred.toString());
            controller.addElementProperty(rendezvousProperty);

            JmxConnector connector = new JmxConnector();
            connector.setName(SYSTEM_CONNECTOR_NAME);
            connector.setAddress(host);
            connector.setPort(port);
            connector.setProtocol(protocol);           
            Ssl ssl = new Ssl();
            ssl.setCertNickname(KeystoreManager.CERTIFICATE_ALIAS);
            connector.setSsl(ssl);

            ElementProperty hostnameProperty = new ElementProperty();
            hostnameProperty.setName(HOST_PROPERTY_NAME);
            hostnameProperty.setValue(clientHostName);
            connector.addElementProperty(hostnameProperty);

            //ISSUE: Not sure how to set the realm name here??? The realm name in the jmx-connector
            //element refers to a realm in the security-service which is associated with a configuration.
            //Unfortunately, the node-agent does not reference a configuration!!!!!!
            connector.setAuthRealmName("admin-realm");
            controller.setJmxConnector(connector);

            // TODO: need to reconcile authrealms ???
            AuthRealm[] authRealms = new AuthRealm[1];
            authRealms[0]=new AuthRealm();
            authRealms[0].setName("admin-realm");
            authRealms[0].setClassname("com.sun.enterprise.security.auth.realm.file.FileRealm");
            ElementProperty fileProperty = new ElementProperty();
            fileProperty.setName("file");
            fileProperty.setValue("${com.sun.aas.instanceRoot}/config/admin-keyfile");
            authRealms[0].addElementProperty(fileProperty);
            ElementProperty jaasContextProperty = new ElementProperty();
            jaasContextProperty.setName("jaas-context");
            jaasContextProperty.setValue("fileRealm");
            authRealms[0].addElementProperty(jaasContextProperty);
            controller.setAuthRealm(authRealms[0]);

            controller.setSystemJmxConnectorName(SYSTEM_CONNECTOR_NAME);

            LogService log = new LogService();
            ModuleLogLevels logLevels = new ModuleLogLevels();
            log.setModuleLogLevels(logLevels);
            log.setFile("${com.sun.aas.instanceRoot}/logs/server.log");
            controller.setLogService(log);

            controllers.addNodeAgent(controller, OVERWRITE);

            //Notify the Node Agent to rendezvous
            //FIXTHIS: We force persistence, clear any notifications, and update the
            //Application server's config context explicitely. Until this is modelled
            //as an event notification (TBD) we need this to happen before notifying or
            //the Node Agent will not synchronize the correct data.
            //QUESTION: What happens if an exception is thrown above (e.g. in addNodeAgent). How do
            //we restore the admin config context to its previous (and unpersisted value)???
            flushAll();
        } catch (Exception ex) {
            throw getExceptionHandler().handleAgentException(
                ex, "nodeagent.addNodeAgent.Exception", nodeAgentName);
        }
    }


    protected void alterNodeAgent(String host, String port,
        String nodeAgentName, String protocol, String clientHostName, Boolean rendezvousOccurred)
        throws AgentException
    {
        try {
            final ConfigContext configContext = getConfigContext();
            // Validate port number since it is a string...
            try {
                Integer.parseInt(port);
            } catch (NumberFormatException ex) {
                throw new AgentException(_strMgr.getString("portMustBeNumeric",
                    port));
            }

            // TODO: get nodeagent to alter, ** need to verify code when dtd is finalized ???
            NodeAgents controllers = ServerBeansFactory.getDomainBean(configContext).getNodeAgents();
            NodeAgent controller = controllers.getNodeAgentByName(nodeAgentName);

            // Alter proper rendezvousProperties
            ElementProperty rendezvousProperty=controller.getElementPropertyByName(RENDEZVOUS_PROPERTY_NAME);
            if (rendezvousProperty != null) {
                controller.removeElementProperty(rendezvousProperty);
            }
           
            rendezvousProperty=new ElementProperty();
            rendezvousProperty.setName(RENDEZVOUS_PROPERTY_NAME);
            rendezvousProperty.setValue(rendezvousOccurred.toString());
            controller.addElementProperty(rendezvousProperty);                        

            // add/alter proper JmxConnector
            JmxConnector connector=controller.getJmxConnector();
            // alter/add attribute information
            connector.setAddress(host);
            connector.setPort(port);
            connector.setProtocol(protocol);

            // set host name for jmxconnector
            ElementProperty hostnameProperty=connector.getElementPropertyByName(HOST_PROPERTY_NAME);
            if(hostnameProperty == null) {
                hostnameProperty=new ElementProperty();
                hostnameProperty.setName(HOST_PROPERTY_NAME);
                connector.addElementProperty(hostnameProperty);
            }
            hostnameProperty.setValue(clientHostName);

            //Notify the Node Agent to rendezvous
            //FIXTHIS: We force persistence, clear any notifications, and update the
            //Application server's config context explicitely. Until this is modelled
            //as an event notification (TBD) we need this to happen before notifying or
            //the Node Agent will not synchronize the correct data.
            //QUESTION: What happens if an exception is thrown above (e.g. in addNodeAgent). How do
            //we restore the admin config context to its previous (and unpersisted value)???
            flushAll();
        } catch (Exception ex) {
            throw getExceptionHandler().handleAgentException(
                ex, "nodeagent.addNodeAgent.Exception", nodeAgentName);
        }
    }
}
TOP

Related Classes of com.sun.enterprise.ee.admin.configbeans.NodeAgentsConfigBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.