co.cask.cdap.gateway.handlers.AbstractMonitorHandler.java Source code

Java tutorial

Introduction

Here is the source code for co.cask.cdap.gateway.handlers.AbstractMonitorHandler.java

Source

/*
 * Copyright  2015-2016 Cask Data, Inc.
 *
 * 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 co.cask.cdap.gateway.handlers;

import co.cask.cdap.app.store.ServiceStore;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.common.twill.MasterServiceManager;
import co.cask.cdap.gateway.handlers.util.AbstractAppFabricHttpHandler;
import co.cask.cdap.proto.SystemServiceMeta;
import co.cask.http.HttpResponder;
import com.google.common.collect.Lists;
import com.google.gson.JsonObject;
import com.google.inject.Inject;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Monitor Handler returns the status of different discoverable services
 */
public class AbstractMonitorHandler extends AbstractAppFabricHttpHandler {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractMonitorHandler.class);

    private final Map<String, MasterServiceManager> serviceManagementMap;
    private static final String STATUSOK = Constants.Monitor.STATUS_OK;
    private static final String STATUSNOTOK = Constants.Monitor.STATUS_NOTOK;
    private static final String NOTAPPLICABLE = "NA";
    private final ServiceStore serviceStore;

    @Inject
    public AbstractMonitorHandler(Map<String, MasterServiceManager> serviceMap, ServiceStore serviceStore)
            throws Exception {
        this.serviceManagementMap = serviceMap;
        this.serviceStore = serviceStore;
    }

    public void getServiceLiveInfo(HttpRequest request, HttpResponder responder, String serviceName)
            throws Exception {
        if (!serviceManagementMap.containsKey(serviceName)) {
            responder.sendString(HttpResponseStatus.NOT_FOUND,
                    String.format("Invalid service name %s", serviceName));
            return;
        }

        MasterServiceManager serviceManager = serviceManagementMap.get(serviceName);
        if (serviceManager.isServiceEnabled()) {
            responder.sendJson(HttpResponseStatus.OK, serviceManager.getLiveInfo());
        } else {
            responder.sendString(HttpResponseStatus.FORBIDDEN,
                    String.format("Service %s is not enabled", serviceName));
        }
    }

    public void getServiceInstance(HttpRequest request, HttpResponder responder, String serviceName)
            throws Exception {
        JsonObject reply = new JsonObject();
        if (!serviceManagementMap.containsKey(serviceName)) {
            responder.sendString(HttpResponseStatus.NOT_FOUND,
                    String.format("Invalid service name %s", serviceName));
            return;
        }
        MasterServiceManager serviceManager = serviceManagementMap.get(serviceName);
        if (serviceManager.isServiceEnabled()) {
            int actualInstance = serviceManagementMap.get(serviceName).getInstances();
            reply.addProperty("provisioned", actualInstance);
            reply.addProperty("requested", getSystemServiceInstanceCount(serviceName));
            responder.sendJson(HttpResponseStatus.OK, reply);
        } else {
            responder.sendString(HttpResponseStatus.FORBIDDEN,
                    String.format("Service %s is not enabled", serviceName));
        }
    }

    public void setServiceInstance(HttpRequest request, HttpResponder responder, String serviceName) {
        try {
            if (!serviceManagementMap.containsKey(serviceName)) {
                responder.sendString(HttpResponseStatus.NOT_FOUND, "Invalid Service Name");
                return;
            }

            MasterServiceManager serviceManager = serviceManagementMap.get(serviceName);
            int instances = getInstances(request);
            if (!serviceManager.isServiceEnabled()) {
                responder.sendString(HttpResponseStatus.FORBIDDEN,
                        String.format("Service %s is not enabled", serviceName));
                return;
            }

            int currentInstances = getSystemServiceInstanceCount(serviceName);
            if (instances < serviceManager.getMinInstances() || instances > serviceManager.getMaxInstances()) {
                String response = String.format("Instance count should be between [%s,%s]",
                        serviceManager.getMinInstances(), serviceManager.getMaxInstances());
                responder.sendString(HttpResponseStatus.BAD_REQUEST, response);
                return;
            } else if (instances == currentInstances) {
                responder.sendStatus(HttpResponseStatus.OK);
                return;
            }

            serviceStore.setServiceInstance(serviceName, instances);
            if (serviceManager.setInstances(instances)) {
                responder.sendStatus(HttpResponseStatus.OK);
            } else {
                responder.sendString(HttpResponseStatus.BAD_REQUEST, "Operation did not succeed");
            }
        } catch (Exception e) {
            responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                    String.format("Error updating instances for service: %s", serviceName));
        }
    }

    public void getBootStatus(HttpRequest request, HttpResponder responder) {
        Map<String, String> result = new HashMap<>();
        for (String service : serviceManagementMap.keySet()) {
            MasterServiceManager masterServiceManager = serviceManagementMap.get(service);
            if (masterServiceManager.isServiceEnabled() && masterServiceManager.canCheckStatus()) {
                String status = masterServiceManager.isServiceAvailable() ? STATUSOK : STATUSNOTOK;
                result.put(service, status);
            }
        }
        responder.sendJson(HttpResponseStatus.OK, result);
    }

    public void monitor(HttpRequest request, HttpResponder responder, String serviceName) {
        if (!serviceManagementMap.containsKey(serviceName)) {
            responder.sendString(HttpResponseStatus.NOT_FOUND,
                    String.format("Invalid service name %s", serviceName));
            return;
        }
        MasterServiceManager masterServiceManager = serviceManagementMap.get(serviceName);
        if (!masterServiceManager.isServiceEnabled()) {
            responder.sendString(HttpResponseStatus.FORBIDDEN,
                    String.format("Service %s is not enabled", serviceName));
            return;
        }
        if (masterServiceManager.canCheckStatus() && masterServiceManager.isServiceAvailable()) {
            JsonObject json = new JsonObject();
            json.addProperty("status", STATUSOK);
            responder.sendJson(HttpResponseStatus.OK, json);
        } else if (masterServiceManager.canCheckStatus()) {
            JsonObject json = new JsonObject();
            json.addProperty("status", STATUSNOTOK);
            responder.sendJson(HttpResponseStatus.OK, json);
        } else {
            responder.sendString(HttpResponseStatus.BAD_REQUEST, "Operation not valid for this service");
        }
    }

    public void getServiceSpec(HttpRequest request, HttpResponder responder) throws Exception {
        List<SystemServiceMeta> response = Lists.newArrayList();
        SortedSet<String> services = new TreeSet<>(serviceManagementMap.keySet());
        List<String> serviceList = new ArrayList<>(services);
        for (String service : serviceList) {
            MasterServiceManager serviceManager = serviceManagementMap.get(service);
            if (serviceManager.isServiceEnabled()) {
                String logs = serviceManager.isLogAvailable() ? Constants.Monitor.STATUS_OK
                        : Constants.Monitor.STATUS_NOTOK;
                String canCheck = serviceManager.canCheckStatus()
                        ? (serviceManager.isServiceAvailable() ? STATUSOK : STATUSNOTOK)
                        : NOTAPPLICABLE;
                //TODO: Add metric name for Event Rate monitoring
                response.add(new SystemServiceMeta(service, serviceManager.getDescription(), canCheck, logs,
                        serviceManager.getMinInstances(), serviceManager.getMaxInstances(),
                        getSystemServiceInstanceCount(service), serviceManager.getInstances()));
            }
        }
        responder.sendJson(HttpResponseStatus.OK, response);
    }

    private int getSystemServiceInstanceCount(String serviceName) throws Exception {
        Integer count = serviceStore.getServiceInstance(serviceName);

        //In standalone mode, this count will be null. And thus we just return the actual instance count.
        if (count == null) {
            return serviceManagementMap.get(serviceName).getInstances();
        } else {
            return count;
        }
    }

    public void restartAllServiceInstances(HttpRequest request, HttpResponder responder, String serviceName) {
        restartInstances(responder, serviceName, -1, true);
    }

    public void restartServiceInstance(HttpRequest request, HttpResponder responder, String serviceName,
            int instanceId) {
        restartInstances(responder, serviceName, instanceId, false);
    }

    private void restartInstances(HttpResponder responder, String serviceName, int instanceId, boolean restartAll) {
        long startTimeMs = System.currentTimeMillis();
        boolean isSuccess = true;
        if (!serviceManagementMap.containsKey(serviceName)) {
            responder.sendString(HttpResponseStatus.NOT_FOUND,
                    String.format("Invalid service name %s", serviceName));
            return;
        }
        MasterServiceManager masterServiceManager = serviceManagementMap.get(serviceName);

        try {
            if (!masterServiceManager.isServiceEnabled()) {
                String message = String.format(
                        "Failed to restart instance for %s because the service is not enabled.", serviceName);
                LOG.debug(message);
                isSuccess = false;
                responder.sendString(HttpResponseStatus.FORBIDDEN, message);
                return;
            }

            if (restartAll) {
                masterServiceManager.restartAllInstances();
            } else {
                if (instanceId < 0 || instanceId >= masterServiceManager.getInstances()) {
                    throw new IllegalArgumentException();
                }
                masterServiceManager.restartInstances(instanceId);
            }
            responder.sendStatus(HttpResponseStatus.OK);
        } catch (IllegalStateException ise) {
            String message = String.format(
                    "Failed to restart instance for %s because the service may not be ready yet", serviceName);
            LOG.debug(message, ise);
            isSuccess = false;
            responder.sendString(HttpResponseStatus.SERVICE_UNAVAILABLE, message);
        } catch (IllegalArgumentException iex) {
            String message = String.format(
                    "Failed to restart instance %d for service: %s because invalid instance id", instanceId,
                    serviceName);
            LOG.debug(message, iex);

            isSuccess = false;
            responder.sendString(HttpResponseStatus.BAD_REQUEST, message);
        } catch (Exception ex) {
            LOG.warn(String.format("Exception when trying to restart instances for service %s", serviceName), ex);

            isSuccess = false;
            responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                    String.format("Error restarting instance %d for service: %s", instanceId, serviceName));
        } finally {
            long endTimeMs = System.currentTimeMillis();
            if (restartAll) {
                serviceStore.setRestartAllInstancesRequest(serviceName, startTimeMs, endTimeMs, isSuccess);
            } else {
                serviceStore.setRestartInstanceRequest(serviceName, startTimeMs, endTimeMs, isSuccess, instanceId);
            }
        }
    }

    public void getLatestRestartServiceInstanceStatus(HttpRequest request, HttpResponder responder,
            String serviceName) {
        try {
            responder.sendJson(HttpResponseStatus.OK, serviceStore.getLatestRestartInstancesRequest(serviceName));
        } catch (IllegalStateException ex) {
            responder.sendString(HttpResponseStatus.NOT_FOUND,
                    String.format("No restart instances request found or %s", serviceName));
        }
    }
}