com.emc.storageos.systemservices.impl.resource.CallHomeServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.emc.storageos.systemservices.impl.resource.CallHomeServiceImpl.java

Source

/*
 * Copyright (c) 2013-2015 EMC Corporation
 * All Rights Reserved
 */

package com.emc.storageos.systemservices.impl.resource;

import java.net.URI;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.ws.rs.core.Response;

import com.emc.storageos.db.client.model.*;
import com.emc.storageos.db.client.model.util.*;
import com.emc.storageos.model.*;
import static com.emc.storageos.svcs.errorhandling.resources.ServiceCode.toServiceCode;
import static com.emc.storageos.svcs.errorhandling.resources.ServiceErrorFactory.toServiceErrorRestRep;
import org.apache.commons.lang.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.emc.storageos.coordinator.client.service.CoordinatorClient.LicenseType;
import com.emc.storageos.coordinator.common.impl.ServiceImpl;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.model.event.EventParameters;
import com.emc.storageos.security.audit.AuditLogManager;
import com.emc.storageos.security.authorization.BasePermissionsHelper;
import com.emc.storageos.services.OperationTypeEnum;
import com.emc.storageos.svcs.errorhandling.resources.APIException;
import com.emc.storageos.svcs.errorhandling.resources.ForbiddenException;
import com.emc.storageos.systemservices.impl.eventhandler.connectemc.BuildEsrsDevice;
import com.emc.storageos.systemservices.impl.eventhandler.connectemc.CallHomeConstants;
import com.emc.storageos.systemservices.impl.eventhandler.connectemc.CallHomeEventManager;
import com.emc.storageos.systemservices.impl.eventhandler.connectemc.CallHomeEventsFacade;
import com.emc.storageos.systemservices.impl.eventhandler.connectemc.SendAlertEvent;
import com.emc.storageos.systemservices.impl.licensing.LicenseInfoExt;
import com.emc.storageos.systemservices.impl.licensing.LicenseInfoListExt;
import com.emc.storageos.systemservices.impl.licensing.LicenseManager;
import com.emc.storageos.systemservices.impl.upgrade.CoordinatorClientExt;

public class CallHomeServiceImpl extends BaseLogSvcResource implements CallHomeService {

    private BuildEsrsDevice _buildEsrsDevice;
    private CallHomeEventsFacade _callHomeEventsFacade;
    private LicenseManager _licenseManager;
    private CallHomeEventManager _callHomeEventManager;
    private static final int FIXED_THREAD_POOL_SIZE = 10;
    private static ExecutorService executorService = null;

    @Autowired
    private AuditLogManager _auditMgr;
    @Autowired
    private DbClient dbClient;
    @Autowired
    protected BasePermissionsHelper permissionsHelper = null;
    @Autowired
    private ServiceImpl serviceInfo;
    @Autowired
    private LogService logService;
    @Autowired
    CoordinatorClientExt coordinator;

    private static final Logger _log = LoggerFactory.getLogger(CallHomeServiceImpl.class);
    private static final String EVENT_SERVICE_TYPE = "callHome";

    private synchronized static ExecutorService getExecutorServiceInstance() {
        if (executorService == null) {
            executorService = Executors.newFixedThreadPool(FIXED_THREAD_POOL_SIZE);
        }
        return executorService;
    }

    @Override
    public TaskResourceRep sendInternalAlert(String source, int eventId, List<String> nodeIds,
            List<String> nodeNames, List<String> logNames, int severity, String start, String end, String msgRegex,
            int maxCount, EventParameters eventParameters) throws Exception {
        _log.info("Sending internal alert for id: {} and source: {}", eventId, source);
        return sendAlert(source, eventId, nodeIds, nodeNames, logNames, severity, start, end, msgRegex, maxCount,
                true, 1, eventParameters);
    }

    @Override
    public TaskResourceRep sendAlert(String source, int eventId, List<String> nodeIds, List<String> nodeNames,
            List<String> logNames, int severity, String start, String end, String msgRegex, int maxCount,
            boolean forceAttachLogs, int force, EventParameters eventParameters) throws Exception {
        if (LogService.runningRequests.get() >= LogService.MAX_THREAD_COUNT) {
            _log.info("Current running requests: {} vs maximum allowed {}", LogService.runningRequests,
                    LogService.MAX_THREAD_COUNT);
            throw APIException.serviceUnavailable.logServiceIsBusy();
        }

        // if not configured for callhome, do not continue.
        _callHomeEventManager.validateSendEvent();

        // validate event id
        if (!CallHomeConstants.VALID_ALERT_EVENT_IDS.contains(eventId)) {
            throw APIException.badRequests.parameterIsNotOneOfAllowedValues("event_id",
                    CallHomeConstants.VALID_ALERT_EVENT_IDS.toString());
        }
        LicenseInfoExt licenseInfo = null;
        // If the user specified a license type to use for sending alerts get it from coordinator
        // Otherwise check if controller or unstructured is licensed
        if (source != null && !source.isEmpty()) {
            // validate source
            LicenseType licenseType = LicenseType.findByValue(source);
            if (licenseType == null) {
                throw APIException.badRequests.parameterIsNotOneOfAllowedValues("source",
                        LicenseType.getValuesAsStrings().toString());
            }
            // get an instance of the requested license information
            licenseInfo = _licenseManager.getLicenseInfoFromCoordinator(licenseType);
            if (licenseInfo == null) {
                throw APIException.internalServerErrors.licenseInfoNotFoundForType(licenseType.toString());
            }
        } else {
            licenseInfo = _licenseManager.getLicenseInfoFromCoordinator(LicenseType.CONTROLLER);
            if (licenseInfo == null) {
                licenseInfo = _licenseManager.getLicenseInfoFromCoordinator(LicenseType.UNSTRUCTURED);
            }
        }

        if (licenseInfo == null) {
            throw ForbiddenException.forbidden.licenseNotFound(
                    LicenseType.CONTROLLER.toString() + " or " + LicenseType.UNSTRUCTURED.toString());
        }

        if (licenseInfo.isTrialLicense()) {
            _log.warn("Cannot send alert to SYR for trial license {} ", licenseInfo.getLicenseType().toString());
            throw APIException.forbidden.permissionDeniedForTrialLicense(licenseInfo.getLicenseType().toString());
        }

        // invoke get-logs api for the dry run
        List<String> logNamesToUse = getLogNamesFromAlias(logNames);
        try {
            logService.getLogs(nodeIds, nodeNames, logNamesToUse, severity, start, end, msgRegex, maxCount, true);
        } catch (Exception e) {
            _log.error("Failed to dry run get-logs, exception: {}", e);
            throw e;
        }

        URI sysEventId = URIUtil.createId(SysEvent.class);
        String opID = UUID.randomUUID().toString();
        SendAlertEvent sendAlertEvent = new SendAlertEvent(serviceInfo, dbClient, _logSvcPropertiesLoader,
                sysEventId, opID, getMediaType(), licenseInfo, permissionsHelper, coordinator);
        sendAlertEvent.setEventId(eventId);
        sendAlertEvent.setNodeIds(nodeIds);
        sendAlertEvent.setLogNames(logNamesToUse);
        sendAlertEvent.setSeverity(severity);
        sendAlertEvent.setStart(getDateTimestamp(start));
        sendAlertEvent.setEnd(getDateTimestamp(end));
        validateMsgRegex(msgRegex);
        sendAlertEvent.setMsgRegex(msgRegex);
        sendAlertEvent.setEventParameters(eventParameters);
        sendAlertEvent.setMaxCount(maxCount);
        sendAlertEvent.setForceAttachLogs(forceAttachLogs);

        // Persisting this operation
        Operation op = new Operation();
        op.setName("SEND ALERT " + eventId);
        op.setDescription("SEND ALERT EVENT code:" + eventId + ", severity:" + severity);
        op.setResourceType(ResourceOperationTypeEnum.SYS_EVENT);
        SysEvent sysEvent = createSysEventRecord(sysEventId, opID, op, force);

        // Starting send event job
        getExecutorServiceInstance().submit(sendAlertEvent);

        auditCallhome(OperationTypeEnum.SEND_ALERT, AuditLogManager.AUDITOP_BEGIN, null, nodeIds, logNames, start,
                end);

        return toTask(sysEvent, opID, op);
    }

    private TaskResourceRep toTask(DataObject resource, String taskId, Operation operation) {
        // If the Operation has been serialized in this request, then it should have the corresponding task embedded in it
        Task task = operation.getTask(resource.getId());
        if (task != null) {
            return toTask(task);
        } else {
            // It wasn't recently serialized, so fallback to looking for the task in the DB
            task = TaskUtils.findTaskForRequestId(dbClient, resource.getId(), taskId);
            if (task != null) {
                return toTask(task);
            } else {
                throw new IllegalStateException(String.format(
                        "Task not found for resource %s, op %s in either the operation or the database",
                        resource.getId(), taskId));
            }
        }
    }

    private TaskResourceRep toTask(Task task) {
        TaskResourceRep taskResourceRep = new TaskResourceRep();

        taskResourceRep.setId(task.getId());
        NamedURI resource = task.getResource();
        NamedRelatedResourceRep namedRelatedResourceRep = new NamedRelatedResourceRep(resource.getURI(),
                new RestLinkRep("self", URI.create("/" + resource.getURI())), resource.getName());
        taskResourceRep.setResource(namedRelatedResourceRep);

        if (!StringUtils.isBlank(task.getRequestId())) {
            taskResourceRep.setOpId(task.getRequestId());
        }

        // Operation
        taskResourceRep.setState(task.getStatus());
        if (task.getServiceCode() != null) {
            taskResourceRep.setServiceError(
                    toServiceErrorRestRep(toServiceCode(task.getServiceCode()), task.getMessage()));
        } else {
            taskResourceRep.setMessage(task.getMessage());
        }
        taskResourceRep.setDescription(task.getDescription());
        taskResourceRep.setStartTime(task.getStartTime());
        taskResourceRep.setEndTime(task.getEndTime());
        taskResourceRep.setProgress(task.getProgress() != null ? task.getProgress() : 0);
        taskResourceRep.setQueuedStartTime(task.getQueuedStartTime());
        taskResourceRep.setQueueName(task.getQueueName());

        return taskResourceRep;
    }

    /**
     * Creates sysevent record after checking if there are any existing records.
     * If force is 1 will not check for existing records.
     */
    private synchronized SysEvent createSysEventRecord(URI sysEventId, String opID, Operation op, int force) {
        if (force != 1) {
            List sysEvents = dbClient.queryByType(SysEvent.class, true);
            if (sysEvents != null && sysEvents.iterator().hasNext()) {
                throw APIException.serviceUnavailable.sendEventBusy();
            }
        }

        _log.info("Event id is {} and operation id is {}", sysEventId, opID);

        SysEvent sysEvent = new SysEvent();
        sysEvent.setId(sysEventId);
        sysEvent.setLabel("System Event");
        dbClient.createObject(sysEvent);

        dbClient.createTaskOpStatus(SysEvent.class, sysEventId, opID, op);
        return sysEvent;
    }

    @Override
    public Response sendRegistrationEvent() {
        internalSendRegistrationEvent();

        return Response.ok().build();
    }

    void internalSendRegistrationEvent() {
        _callHomeEventManager.validateSendEvent();
        LicenseInfoListExt licenseList = null;
        try {
            licenseList = _licenseManager.getLicenseInfoListFromCoordinator();
        } catch (Exception e) {
            throw APIException.internalServerErrors.licenseInfoNotFoundForType("all license types");
        }
        if (licenseList != null) {
            // send registration events for each registered license type
            for (LicenseInfoExt licenseInfo : licenseList.getLicenseList()) {
                if (licenseInfo.isTrialLicense()) {
                    _log.warn("Cannot send regisration event to SYR for trial license {}",
                            licenseInfo.getLicenseType().toString());
                    throw APIException.forbidden
                            .permissionDeniedForTrialLicense(licenseInfo.getLicenseType().toString());
                }
                _callHomeEventsFacade.sendRegistrationEvent(licenseInfo, getMediaType());
            }
        }
        auditCallhome(OperationTypeEnum.SEND_REGISTRATION, AuditLogManager.AUDITLOG_SUCCESS, null);
    }

    @Override
    public Response sendHeartbeatEvent() {

        // if not configured for callhome, do not continue.
        _callHomeEventManager.validateSendEvent();

        LicenseInfoListExt licenseList = null;
        try {
            licenseList = _licenseManager.getLicenseInfoListFromCoordinator();
        } catch (Exception e) {
            throw APIException.internalServerErrors.licenseInfoNotFoundForType("all license types");
        }
        if (licenseList != null) {
            // send heart beat events for each registered license type
            for (LicenseInfoExt licenseInfo : licenseList.getLicenseList()) {
                if (licenseInfo.isTrialLicense()) {
                    _log.warn("Cannot send heartbeat event to SYR for trial license {} ",
                            licenseInfo.getLicenseType().toString());
                    throw APIException.forbidden
                            .permissionDeniedForTrialLicense(licenseInfo.getLicenseType().toString());
                }

                _callHomeEventsFacade.sendHeartBeatEvent(licenseInfo, getMediaType());
            }
        }

        auditCallhome(OperationTypeEnum.SEND_HEARTBEAT, AuditLogManager.AUDITLOG_SUCCESS, null);

        return Response.ok().build();
    }

    @Override
    public Response getNodeDataForEsrs() {

        try {
            auditCallhome(OperationTypeEnum.CREATE_ESRS_CONFIGURATION, AuditLogManager.AUDITLOG_SUCCESS, null);
            return Response.status(200).entity(_buildEsrsDevice.build()).build();
        } catch (Exception e) {
            throw APIException.badRequests.getNodeDataForESRSFailure(e);
        }
    }

    /**
     * Spring Injected BuildEsrsConfigurationFile
     */
    @Autowired
    public void setCallHomeEventsFacade(CallHomeEventsFacade callHomeEventsFacade) {
        this._callHomeEventsFacade = callHomeEventsFacade;
    }

    /**
     *
     */
    @Autowired
    public void setBuildEsrsDevice(BuildEsrsDevice buildEsrsDevice) {
        _buildEsrsDevice = buildEsrsDevice;
    }

    /**
     * Record audit log for callhome service
     * 
     * @param auditType Type of AuditLog
     * @param operationalStatus Status of operation
     * @param description Description for the AuditLog
     * @param descparams Description paramters
     */
    public void auditCallhome(OperationTypeEnum auditType, String operationalStatus, String description,
            Object... descparams) {

        _auditMgr.recordAuditLog(null, null, EVENT_SERVICE_TYPE, auditType, System.currentTimeMillis(),
                operationalStatus, description, descparams);
    }

    /**
     * Set the CallHomeEventManager
     */
    @Autowired
    public void setLicenseManager(LicenseManager licenseManager) {
        _licenseManager = licenseManager;
    }

    /**
     * Set the CallHomeEventManager
     */
    @Autowired
    public void setCallHomeEventManager(CallHomeEventManager callHomeEventManager) {
        _callHomeEventManager = callHomeEventManager;
    }
}