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

com.sun.enterprise.v3.admin.cluster.ListInstancesCommand Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2010-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 [2018-2023] [Payara Foundation and/or its affiliates]
package com.sun.enterprise.v3.admin.cluster;

import com.sun.enterprise.admin.util.InstanceStateService;
import com.sun.enterprise.admin.util.RemoteInstanceCommandHelper;
import com.sun.enterprise.config.serverbeans.*;
import com.sun.enterprise.util.StringUtils;
import com.sun.enterprise.util.SystemPropertyConstants;
import com.sun.enterprise.util.cluster.InstanceInfo;
import static com.sun.enterprise.v3.admin.cluster.Constants.*;
import fish.payara.enterprise.config.serverbeans.DeploymentGroup;
import java.util.*;
import java.util.logging.*;
import jakarta.inject.Inject;
import org.glassfish.api.ActionReport;
import org.glassfish.api.ActionReport.ExitCode;
import org.glassfish.api.I18n;
import org.glassfish.api.Param;
import org.glassfish.api.admin.*;
import org.glassfish.api.admin.config.ReferenceContainer;
import org.glassfish.hk2.api.PerLookup;
import org.glassfish.hk2.api.ServiceLocator;
import org.jvnet.hk2.annotations.Service;

/**
 * AdminCommand to list all instances and their states
 *
 * This is so clumsy & hard to remember I leave it here as a comment:
 * @Inject(name = ServerEnvironment.DEFAULT_INSTANCE_NAME)
 * @author Byron Nevins
 */
@org.glassfish.api.admin.ExecuteOn(RuntimeType.DAS)
@Service(name = "list-instances")
@CommandLock(CommandLock.LockType.NONE)
@I18n("list.instances.command")
@PerLookup
@RestEndpoints({
    @RestEndpoint(configBean=Cluster.class,
        opType=RestEndpoint.OpType.GET,
        path="list-instances",
        description="List Cluster Instances",
        params={
            @RestParam(name="id", value="$parent")
        }),
    @RestEndpoint(configBean=Domain.class,
        opType=RestEndpoint.OpType.GET,
        path="list-instances",
        description="List Instances"),
    @RestEndpoint(configBean=DeploymentGroup.class,
        opType=RestEndpoint.OpType.GET,
        path="list-instances",
        description="List Cluster Instances",
        params={
            @RestParam(name="id", value="$parent")
        })
})
public class ListInstancesCommand implements AdminCommand {

    @Inject
    private ServiceLocator habitat;
    @Inject
    private Domain domain;
    @Inject
    private ServerEnvironment env;
    @Inject
    private Servers allServers;
    @Inject
    InstanceStateService stateService;
    @Param(optional = true, defaultValue = "false", name = "long", shortName = "l")
    private boolean long_opt;
    @Param(optional = true, defaultValue = "-1")
    private String timeoutmsec;
    @Param(optional = true, defaultValue = "false")
    private boolean standaloneonly;
    @Param(optional = true, defaultValue = "false")
    private boolean nostatus;

    // We are setting the whichTarget to an empty String because FindBugs - LL
    // does not understand that HK2 is going to set it to a Sting for us later.
    // This garbage empty String will be replaced by HK2 soon...
    @Param(optional = true, primary = true, defaultValue = "domain")
    String whichTarget = "";

    private List infos = new LinkedList<>();
    private List serverList;
    private ActionReport report;
    private ActionReport.MessagePart top = null;
    private static final String EOL = "\n";
    private static final String READ_TIMEOUT_KEY = "AS_ADMIN_READTIMEOUT";
    private static final String LIST_INSTANCES_TIMEOUT_KEY = "AS_ADMIN_LISTINSTANCESTIMEOUT";

    private int getDefaultTimeout() {
        String ct = System.getProperty(LIST_INSTANCES_TIMEOUT_KEY);
        if (ct == null) {
            ct = System.getenv(LIST_INSTANCES_TIMEOUT_KEY);
        }
        if (ct == null) {
            ct = System.getProperty(READ_TIMEOUT_KEY);
        }
        if (ct == null) {
            ct = System.getenv(READ_TIMEOUT_KEY);
        }
        if (ct != null) {
            return Integer.parseInt(ct);
        } else {
            return 10 * 1000;       // 10 seconds
        }

    }
    
    @Override
    public void execute(AdminCommandContext context) {
        // setup
        int timeoutInMsec;
        try {
            timeoutInMsec = Integer.parseInt(timeoutmsec);
            if (timeoutInMsec < 0) {
                timeoutInMsec = getDefaultTimeout();
            }
        }
        catch (Exception e) {
            timeoutInMsec = getDefaultTimeout();
        }

        report = context.getActionReport();
        top = report.getTopMessagePart();

        Logger logger = context.getLogger();

        if (!validateParams()) {
            return;
        }

        serverList = createServerList();

        if (serverList == null) {
            fail(Strings.get("list.instances.badTarget", whichTarget ));
            return;
        }
        // Require that we be a DAS
        if (!env.isDas()) {
            String msg = Strings.get("list.instances.onlyRunsOnDas");
            logger.warning(msg);
            fail(msg);
            return;
        }

        if (nostatus) {
            noStatus(serverList);
        }
        else {
            yesStatus(serverList, timeoutInMsec, logger);
        }

        report.setActionExitCode(ExitCode.SUCCESS);
    }

    private void noStatus(List serverList) {
        if (serverList.isEmpty()) {
            report.setMessage(NONE);
            return;
        }

        StringBuilder sb = new StringBuilder();
        boolean firstServer = true;
        Properties extraProps = new Properties();
        List> instanceList = new ArrayList<>();

        for (Server server : serverList) {
            boolean clustered = server.getCluster() != null;

            if (standaloneonly && clustered) {
                continue;
            }

            String name = server.getName();

            if (notDas(name)) {
                if (firstServer) {
                    firstServer = false;
                }
                else {
                    sb.append(EOL);
                }

                sb.append(name);
                top.addProperty(name, "");
                Map insDetails = new HashMap<>();
                insDetails.put("name", name);
                instanceList.add(insDetails);
            }
        }
        extraProps.put("instanceList", instanceList);
        report.setMessage(sb.toString());
        report.setExtraProperties(extraProps);
    }

    private boolean notDas(String name) {
        return !SystemPropertyConstants.DAS_SERVER_NAME.equals(name);
    }

    private void yesStatus(List serverList, int timeoutInMsec, Logger logger) {
        // Gather a list of InstanceInfo -- one per instance in domain.xml
        RemoteInstanceCommandHelper helper = new RemoteInstanceCommandHelper(habitat);

        for (Server server : serverList) {
            boolean clustered = server.getCluster() != null;
            int port = helper.getAdminPort(server);
            String host = server.getAdminHost();

            if (standaloneonly && clustered) {
                continue;
            }

            String name = server.getName();

            if (name == null) {
                continue;   // can this happen?!?
            }
            
            StringBuilder deploymentGroup = new StringBuilder();
            for (DeploymentGroup dg : server.getDeploymentGroup()) {
                deploymentGroup.append(dg.getName()).append(' ');
            }

            Cluster cluster = domain.getClusterForInstance(name);
            String clusterName = (cluster != null) ? cluster.getName() : null;
            // skip DAS
            if (notDas(name)) {
                ActionReport tReport = habitat.getService(ActionReport.class, "html");
                InstanceInfo ii = new InstanceInfo(
                        habitat,
                        server,
                        port,
                        host,
                        clusterName,
                        deploymentGroup.toString(),
                        logger,
                        timeoutInMsec,
                        tReport,
                        stateService);
                infos.add(ii);
            }
        }
        if (infos.isEmpty()) {
            report.setMessage(NONE);
            return;
        }

        Properties extraProps = new Properties();
        List> instanceList = new ArrayList<>();

        infos.sort(Comparator.comparing(InstanceInfo::getName));
        for (InstanceInfo ii : infos) {
            String name = ii.getName();
            String value = (ii.isRunning()) ? InstanceState.StateType.RUNNING.getDescription()
                    : InstanceState.StateType.NOT_RUNNING.getDescription();
            InstanceState.StateType state = (ii.isRunning())
                    ? (stateService.setState(name, InstanceState.StateType.RUNNING, false))
                    : (stateService.setState(name, InstanceState.StateType.NOT_RUNNING, false));
            List failedCmds = stateService.getFailedCommands(name);
            if (state == InstanceState.StateType.RESTART_REQUIRED) {
                if (ii.isRunning()) {
                    value = InstanceState.StateType.RESTART_REQUIRED.getDescription();
                }
            }

            Map insDetails = new HashMap<>();
            insDetails.put("name", name);
            insDetails.put("status", value);
            insDetails.put("deploymentgroup", ii.getDeploymentGroups().trim());
            if (state == InstanceState.StateType.RESTART_REQUIRED) {
                insDetails.put("restartReasons", failedCmds);
            }
            if (ii.isRunning()) {
                insDetails.put("uptime", ii.getUptime());
            }
            instanceList.add(insDetails);
        }
        extraProps.put("instanceList", instanceList);
        report.setExtraProperties(extraProps);

        if (long_opt) {
            report.setMessage(InstanceInfo.format(infos));
        }
        else {
            report.setMessage(InstanceInfo.formatBrief(infos));
        }
    }

    /*
     * return null means the whichTarget is garbage
     * return empty list means the whichTarget was an empty cluster
     */
    private List createServerList() {
        // 1. no whichTarget specified
        if (!StringUtils.ok(whichTarget))
            return allServers.getServer();

        ReferenceContainer rc = domain.getReferenceContainerNamed(whichTarget);
        // 2. Not a server or a cluster. Could be a config or a Node
        if (rc == null) {
            return getServersForNodeOrConfig();
        }
        else if (rc.isServer()) {
            List l = new LinkedList<>();
            l.add((Server) rc);
            return l;
        }
        else if (rc.isCluster()) { 
            Cluster cluster = (Cluster) rc;
            return cluster.getInstances();
        }
        else if (rc.isDeploymentGroup()) {
            DeploymentGroup deploymentGroup = (DeploymentGroup) rc;
            return deploymentGroup.getInstances();
        }
        else {
            return null;
        }
    }

    private List getServersForNodeOrConfig() {
        if (whichTarget == null)
            throw new NullPointerException("impossible!");

        List list = getServersForNode();

        if (list == null) {
            list = getServersForConfig();
        }
        
        if (list == null) {
            list = getServersForDeploymentGroup();
        }

        return list;
    }

    private List getServersForNode() {
        if (whichTarget == null) // FindBugs can't figure out that our caller already checked.
            throw new NullPointerException("impossible!");

        boolean foundNode = false;
        Nodes nodes = domain.getNodes();

        if (nodes != null) {
            List nodeList = nodes.getNode();
            if (nodeList != null) {
                for (Node node : nodeList) {
                    if (whichTarget.equals(node.getName())) {
                        foundNode = true;
                        break;
                    }
                }
            }
        }
        if (!foundNode) {
            return null;
        }
        else {
            return domain.getInstancesOnNode(whichTarget);
        }
    }

    private List getServersForConfig() {
        Config config = domain.getConfigNamed(whichTarget);

        if (config == null) {
            return null;
        }

        List rcs = domain.getReferenceContainersOf(config);
        List servers = new LinkedList<>();

        for (ReferenceContainer rc : rcs) {
            if (rc.isServer()) {
                servers.add((Server) rc);
            }
        }

        return servers;
    }

    /*
     * false means error
     */
    private boolean validateParams() {
        // another sort of weird scenario is that if the whichTarget is set to "domain",
        // that means ALL instances in the domains.  To make life easier -- we just
        //set the whichTarget to zilch to signal all instances in domain

        if ("domain".equals(whichTarget)) {
            whichTarget = null;
        }

        // standaloneonly AND a whichTarget are mutually exclusive
        if (standaloneonly && StringUtils.ok(whichTarget)) {
            fail(Strings.get("list.instances.targetWithStandaloneOnly"));
            return false;
        }

        // long_opt is not allowed with nostatus.
        // It could be allowed in the future if desired but the table code needs
        // to change.
        if (long_opt && nostatus) {
            fail(Strings.get("list.instances.longAndNoStatus"));
            return false;
        }

        // details details details!
        // if the whichTarget is the weird screwy "server" then fail.
        // TODO - we *could* show DAS status in the future but it's stupid
        // since this command ONLY runs on DAS -- it is obviously running!!

        if (!notDas(whichTarget)) {
            fail(Strings.get("list.instances.serverTarget"));
            return false;
        }
        return true;
    }

    // avoid ugly boilerplate...
    private void fail(String s) {
        report.setActionExitCode(ActionReport.ExitCode.FAILURE);
        report.setMessage(s);
    }

    private List getServersForDeploymentGroup() {
        List result = null;
        DeploymentGroup dg = domain.getDeploymentGroupNamed(whichTarget);
        if (dg != null) {
            result = dg.getInstances();
        }
        return result;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy