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

org.glassfish.jms.admin.cli.ConfigureJMSCluster Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2013 Oracle and/or its affiliates. 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_1_1.html
 * or packager/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 packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [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.
 */
// Portions Copyright [2020-2021] [Payara Foundation and/or its affiliates]

package org.glassfish.jms.admin.cli;

import com.sun.enterprise.config.serverbeans.*;
import com.sun.enterprise.connectors.jms.config.JmsAvailability;
import com.sun.enterprise.connectors.jms.config.JmsService;
import com.sun.enterprise.util.LocalStringManagerImpl;
import java.beans.PropertyVetoException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import jakarta.inject.Inject;
import org.glassfish.api.ActionReport;
import org.glassfish.api.I18n;
import org.glassfish.api.Param;
import org.glassfish.api.admin.*;
import org.glassfish.hk2.api.PerLookup;
import org.glassfish.hk2.api.ServiceLocator;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.ConfigSupport;
import org.jvnet.hk2.config.SingleConfigCode;
import org.jvnet.hk2.config.TransactionFailure;
import org.jvnet.hk2.config.types.Property;


/**
 * Configure JMS Cluster Command
 *
 */
@Service(name="configure-jms-cluster")
@PerLookup
@I18n("configure.jms.cluster")
@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
//@TargetType({CommandTarget.CLUSTER})
@RestEndpoints({
    @RestEndpoint(configBean=Cluster.class,
        opType=RestEndpoint.OpType.POST, 
        path="configure-jms-cluster", 
        description="configure-jms-cluster",
        params={
            @RestParam(name="id", value="$parent")
        })
})
public class ConfigureJMSCluster implements AdminCommand {
    final private static String SUPPORTED_DB_VENDORS = "oracle|postgresql|mysql|h2|db2|sqlserver";
    final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(ConfigureJMSCluster.class);
    final private static String MASTER_BROKER = "masterbroker";
    final private static String SHARED_DB = "shareddb";
    final private static String FILE = "file";
    final private static String JDBC = "jdbc";
    final private static String CONVENTIONAL = "conventional";
    final private static String ENHANCED = "enhanced";
    final private static String LOCAL = "LOCAL";
    final private static String REMOTE = "REMOTE";
    final private static String EMBEDDED = "EMBEDDED";
    final private static String PASSWORD_KEY="AS_ADMIN_JMSDBPASSWORD";
    // [usemasterbroker] [availability-enabled] [dbvendor] [dbuser] [dbpassword admin] [jdbcurl] [properties props] clusterName
    /*
    configure-jms-cluster [--clustertype =conventional | enhanced] [--messagestoretype=jdbc | file] [--configstoretype=masterbroker | shareddb] [--dbvendor] [--dbuser] [--dbpassword]  [--dburl] [--force] [--property (name=value)[:name-value]*] clusterName

    a. Message store type (JDBC | file) - defaults to file

    b. Config store type (MasterBroker | SharedDB) - defaults to MasterBroker
    c. Cluster Type: Conventional | Enhanced (if enhanced, then (a) and (b) are ignored).
     */

    @Param(name="configstoretype", optional=true, alias="cs")
    String configStoreType;

    @Param(name="messagestoretype", optional=true, alias="ms")
    String messageStoreType;

    @Param(name="clustertype", alias="ct", optional=false)
    String clusterType;

    @Param(name="dbvendor", alias="db", optional=true)
    String dbvendor;

    @Param(name="dbuser", alias="user", optional=true)
    String dbuser;

    @Param(name="jmsDbPassword", optional=true, password=true)
    String jmsDbPassword ;

    @Param(name="dburl", alias="url", optional=true)
    String dburl;

    @Param(name="property", optional=true, separator=':')
    Properties props;

    //@Param(name="force", defaultValue="false", optional=true)
    //boolean force;

    @Param(primary=true)
    String clusterName;

    @Inject
    Domain domain;

    @Inject
    ServiceLocator habitat;

    @Inject
    CommandRunner commandRunner;

    Config config;

    /**
     * Executes the command with the command parameters passed as Properties
     * where the keys are the paramter names and the values the parameter values
     *
     * @param context information
     */
    public void execute(AdminCommandContext context) {
        final ActionReport report = context.getActionReport();
       // Server targetServer = domain.getServerNamed(target);
        //String configRef = targetServer.getConfigRef();

        Cluster cluster =domain.getClusterNamed(clusterName);

        if (cluster == null) {
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.invalidClusterName",
                            "No Cluster by this name has been configured"));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
        }

        List instances = cluster.getInstances();

        String warning = null;
        if(instances.size() > 0) {
            ActionReport listReport = habitat.getService(ActionReport.class);
            ParameterMap parameters = new ParameterMap();
            parameters.set("DEFAULT", clusterName);
            commandRunner.getCommandInvocation("list-instances", listReport, context.getSubject()).parameters(parameters).execute();

            if (ActionReport.ExitCode.FAILURE.equals(listReport.getActionExitCode())) {
                warning = localStrings.getLocalString("configure.jms.cluster.clusterWithInstances",
                                    "Warning: Please make sure running this command with all cluster instances stopped, otherwise it may lead to inconsistent JMS behavior and corruption of configuration and message stores.");
            } else {
                String result = listReport.getMessage();
                String fixedResult = result.replaceAll("not running", "stopped");
                if (fixedResult.indexOf("running") > -1) {
                    warning = localStrings.getLocalString("configure.jms.cluster.clusterWithInstances",
                                    "Warning: Please make sure running this command with all cluster instances stopped, otherwise it may lead to inconsistent JMS behavior and corruption of configuration and message stores.");
                    warning = warning + "\r\n" + result + "\r\n";
                }
            }
        }

        Config config = domain.getConfigNamed(cluster.getConfigRef());
        JmsService jmsService = config.getExtensionByType(JmsService.class);

        if(jmsService == null) {
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.nojmsservice",
                            "No JMS Service element in config"));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
        }

        if(! CONVENTIONAL.equalsIgnoreCase(clusterType) && ! ENHANCED.equalsIgnoreCase(clusterType)){
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.wrongClusterType",
                            "Invalid option sepecified for clustertype. Valid options are conventional and enhanced"));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
        }

        if (CONVENTIONAL.equalsIgnoreCase(clusterType) && ! MASTER_BROKER.equalsIgnoreCase(configStoreType) && ! SHARED_DB.equalsIgnoreCase(configStoreType)){
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.wrongConfigStoreType",
                            "Invalid option sepecified for configstoretype. Valid options are masterbroker and shareddb"));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
        }
        if(ENHANCED.equalsIgnoreCase(clusterType) && configStoreType  != null){
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.wrongStoreType",
                            "configstoretype option is not configurable for Enhanced clusters."));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
        }
        if (CONVENTIONAL.equalsIgnoreCase(clusterType) && ! MASTER_BROKER.equalsIgnoreCase(configStoreType) && ! FILE.equalsIgnoreCase(messageStoreType) && ! JDBC.equalsIgnoreCase(messageStoreType)){
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.wrongMessageStoreType",
                            "Invalid option sepecified for messagestoretype. Valid options are file and jdbc"));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
        }
        if(ENHANCED.equalsIgnoreCase(clusterType) && messageStoreType  != null){
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.wrongmsgStoreType",
                            "messagestoretype option is not configurable for Enhanced clusters."));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
        }

        String integrationMode = jmsService.getType();
        if(REMOTE.equalsIgnoreCase(integrationMode)) {
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.remoteMode",
                            "JMS integration mode should be either EMBEDDED or LOCAL to run this command. Please use the asadmin.set command to change the integration mode"));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
        }
        String changeIntegrationMode = null;
        if(EMBEDDED.equalsIgnoreCase(integrationMode) && ENHANCED.equalsIgnoreCase(clusterType)) {
            try {
                ConfigSupport.apply(new SingleConfigCode() {
                    public Object run(JmsService param) throws PropertyVetoException, TransactionFailure {
                        param.setType(LOCAL);
                        return param;
                    }
                }, jmsService);
                changeIntegrationMode = localStrings.getLocalString("configure.jms.cluster.integrationModeChanged",
                                                                  "WARNING: JMS integration mode has been changed from EMBEDDED to LOCAL automatically.");
            } catch(TransactionFailure tfe) {
                report.setMessage(localStrings.getLocalString("configure.jms.cluster.cannotChangeIntegrationMode",
                                "Unable to change the JMS integration mode to LOCAL for Enhanced cluster {0}.", clusterName) + " " + tfe.getLocalizedMessage());
                report.setActionExitCode(ActionReport.ExitCode.FAILURE);
                report.setFailureCause(tfe);
                return;
            }
        }
        if (MASTER_BROKER.equalsIgnoreCase(configStoreType) && FILE.equals(messageStoreType)){

            if(dbvendor != null || dburl != null || dbuser != null) {
                report.setMessage(localStrings.getLocalString("configure.jms.cluster.invalidDboptions",
                            "Database options should not be specified for this configuration"));
                report.setActionExitCode(ActionReport.ExitCode.FAILURE);
                return;
            }
        }
        if(! MASTER_BROKER.equalsIgnoreCase(configStoreType) || ENHANCED.equalsIgnoreCase(clusterType) || JDBC.equalsIgnoreCase(messageStoreType)){
          if (dbvendor == null) {
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.nodbvendor",
                            "No DataBase vendor specified"));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
         }
         else if (dburl == null) {
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.nojdbcurl",
                            "No JDBC URL specified"));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
         }
         else if (! isSupportedDbVendor()){
             report.setMessage(localStrings.getLocalString("configure.jms.cluster.invaliddbvendor",
                            "Invalid DB Vednor specified"));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
         }
        }
        if(CONVENTIONAL.equalsIgnoreCase(clusterType) && configStoreType  == null){
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.noConfigStoreType",
                            "No configstoretype specified. Using the default value - masterbroker"));
            configStoreType="masterbroker";
        }
        if(CONVENTIONAL.equalsIgnoreCase(clusterType) && messageStoreType  == null){
            report.setMessage(localStrings.getLocalString("configure.jms.cluster.noMessagetoreType",
                            "No messagestoretype specified. Using the default value - file"));
            messageStoreType="file";
        }


        config = domain.getConfigNamed(cluster.getConfigRef());

        JmsAvailability jmsAvailability = config.getAvailabilityService().getExtensionByType(JmsAvailability.class);
        final Boolean availabilityEnabled = Boolean.valueOf(ENHANCED.equalsIgnoreCase(clusterType));

        try {
            ConfigSupport.apply(new SingleConfigCode() {
                public Object run(JmsAvailability param) throws PropertyVetoException, TransactionFailure {
                    param.setAvailabilityEnabled(availabilityEnabled.toString());
                    if(availabilityEnabled.booleanValue()){
                        param.setMessageStoreType(JDBC);
                    }
                    else{
                        param.setConfigStoreType(configStoreType.toLowerCase(Locale.ENGLISH));
                        param.setMessageStoreType(messageStoreType.toLowerCase(Locale.ENGLISH));
                    }
                    param.setDbVendor(dbvendor);
                    param.setDbUsername(dbuser);
                    param.setDbPassword(jmsDbPassword);
                    param.setDbUrl(dburl);

                    if(props != null)
                    {
                       for (Map.Entry e: props.entrySet()){
                        Property prop = param.createChild(Property.class);
                        prop.setName((String)e.getKey());
                        prop.setValue((String)e.getValue());
                        param.getProperty().add(prop);
                        }
                    }
                    return param;
                  }
               }, jmsAvailability);

           /* //update the useMasterBroker flag on the JmsService only if availabiltyEnabled is false
            if(!availabilityEnabled.booleanValue()){
              ConfigSupport.apply(new SingleConfigCode() {
                public Object run(JmsService param) throws PropertyVetoException, TransactionFailure {

                    param.setUseMasterBroker(useMasterBroker.toString());
                    return param;
                }
            }, jmsservice);
            }*/

        } catch(TransactionFailure tfe) {
            report.setMessage((changeIntegrationMode == null ? "" : changeIntegrationMode + "\n") +
                            localStrings.getLocalString("configure.jms.cluster.fail",
                            "Unable to Configure JMS Cluster for cluster {0}.", clusterName) +
                            " " + tfe.getLocalizedMessage());
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            report.setFailureCause(tfe);
        }

        report.setMessage((warning == null ? "" : warning + "\n") + (changeIntegrationMode == null ? "" : changeIntegrationMode + "\n") +
                localStrings.getLocalString("configure.jms.cluster.success", "JMS Cluster Configuration updated for Cluster {0}.", clusterName));
        report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
    }

    private boolean isSupportedDbVendor(){
        if (dbvendor != null)
        {
            return SUPPORTED_DB_VENDORS.contains(dbvendor.toLowerCase(Locale.ENGLISH));
        }
        return false;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy