/*
* Copyright (c) 2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.systemservices.impl.eventhandler.connectemc;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.core.MediaType;
import com.emc.storageos.svcs.errorhandling.resources.APIException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.emc.storageos.coordinator.client.service.CoordinatorClient.LicenseType;
import com.emc.storageos.systemservices.impl.licensing.LicenseInfoExt;
import com.emc.storageos.systemservices.impl.licensing.LicenseInfoListExt;
import com.emc.storageos.systemservices.impl.licensing.LicenseManager;
@Service
public class SendEventScheduler implements Runnable {
private CallHomeEventManager _callHomeEventManager;
private LicenseManager _licenseManager;
private CallHomeEventsFacade _callHomeEventsFacade;
private static final Logger _log = LoggerFactory.getLogger(SendEventScheduler.class);
/**
* Sets up the scheduler.
*/
public SendEventScheduler() {
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(this, CallHomeConstants.SERVICE_START_LAG, CallHomeConstants.LAG_BETWEEN_RUNS, TimeUnit.SECONDS);
}
/**
*
* Method which sends the Heartbeat event and also verifies if the license
* has expired. If so, it will send a license expiration event.
*
* Runs once per day.
*/
@Override
public void run() {
_log.info("SendEventScheduler::run() start");
// if customer is not configured to send callhome events to SYR, do not continue.
try {
if (!_callHomeEventManager.canSendEvent()) {
return;
}
int totalSleep = 0;
while (true) {
if (_licenseManager.getTargetInfoLock()) {
// verify if there are any eligible callhome events for the license type to be sent.
try {
performSendEvents();
} catch (Exception e) {
_log.error("Exception sending events to SYR: {} ", e);
break;
} finally {
_licenseManager.releaseTargetVersionLock();
}
break;
}
else {
_log.info("Cannot acquire TargetLock. Sleeping 5s before retrying...");
if (totalSleep >= CallHomeConstants.MAX_LOCK_WAIT_TIME_MS) {
_log.warn("Cannot acquire TargetLock in {}ms. So quitting SendEventScheduler",
CallHomeConstants.MAX_LOCK_WAIT_TIME_MS);
break;
}
Thread.sleep(CallHomeConstants.LOCK_WAIT_TIME_MS); // 5s
totalSleep += CallHomeConstants.LOCK_WAIT_TIME_MS;
}
}
} catch (APIException i) {
_log.info("ConnectEMC is not configured. Ending SendEventScheduler.");
} catch (Exception e) {
_log.error("Exception while running event scheduler: {} ", e);
}
_log.info("SendEventScheduler::run() end");
}
/**
* Send eligible events based on their license type (CONTROLLER or OBJECT)
*
* @param licenseType
*/
private void performSendEvents() {
LicenseInfoListExt licenseList = null;
try {
licenseList = _licenseManager.getLicenseInfoListFromCoordinator();
} catch (Exception e) {
_log.error("SendEventScheduler::performSendEvents(): getLicenseInfoListFromCoordinator exception: {}", e.getMessage());
return;
}
if (licenseList != null) {
for (LicenseInfoExt licenseInfo : licenseList.getLicenseList()) {
_log.info("SendEventScheduler::run() getting LicenseInfoExt for {}", licenseInfo.getLicenseType());
try {
if (!licenseInfo.isTrialLicense()) {
if (_callHomeEventManager.doSendHeartBeat(licenseInfo)) {
sendHeartbeat(licenseInfo);
}
if (_licenseManager.isLicenseExpired(licenseInfo) &&
_callHomeEventManager.doSendLicenseExpiration(licenseInfo)) {
sendLicenseExpiration(licenseInfo);
}
// In case user has not import 2.0 license after upgrade, Capacity exceeded
// event from existing 1.0 license of HDFS/OBJECT/OBJECTHDFS should be blocked.
LicenseType licType = licenseInfo.getLicenseType();
if (licType == LicenseType.OBJECTHDFS ||
licType == LicenseType.OBJECT || licType == LicenseType.HDFS) {
continue;
}
/* TODO: enable compliance check after Yoda
if (licenseInfo.hasStorageCapacity() &&
_licenseManager.isCapacityExceeded(licenseInfo) &&
_callHomeEventManager.doSendCapicityExceeded(licenseInfo)) {
sendCapacityExceeded(licenseInfo);
}
*/
}
} catch (Exception e) {
_log.error("SendEventScheduler::performSendEvents(): Exception: {}", e.getMessage());
continue;
}
}
}
}
/**
* Send Registration event to SYR.
*/
private void sendRegistration(LicenseInfoExt licenseInfo)
throws Exception {
_log.info("SendEventScheduler::sendRegistration() for {}",
licenseInfo.getLicenseType());
_callHomeEventsFacade.sendRegistrationEvent(licenseInfo, MediaType.APPLICATION_XML_TYPE);
}
/**
* Send Heartbeat event to SYR.
*/
private void sendHeartbeat(LicenseInfoExt licenseInfo)
throws Exception {
_log.info("SendEventScheduler::sendHeartbeat() for {}",
licenseInfo.getLicenseType());
_callHomeEventsFacade.sendHeartBeatEvent(licenseInfo, MediaType.APPLICATION_XML_TYPE);
}
/**
* Send License Expiration event to SYR.
*/
private void sendLicenseExpiration(LicenseInfoExt licenseInfo)
throws Exception {
_log.info("SendEventScheduler::validateAndSendLicenseExpiration() for {}",
licenseInfo.getLicenseType());
_callHomeEventsFacade.sendExpirationEvent(licenseInfo, MediaType.APPLICATION_XML_TYPE);
}
/**
* Send Capacity Exceeded event to SYR
*
* @param licenseInfo
* @throws Exception
*/
private void sendCapacityExceeded(LicenseInfoExt licenseInfo)
throws Exception {
_log.info("SendEventScheduler::validateAndSendCapacityExceeded() for {}",
licenseInfo.getLicenseType());
_callHomeEventsFacade.sendCapacityExceededEvent(licenseInfo, MediaType.APPLICATION_XML_TYPE);
}
/**
* Set the CallHomeEventManager
*
* @param callHomeEventManager
*/
@Autowired
public void setCallHomeEventManager(CallHomeEventManager callHomeEventManager) {
_callHomeEventManager = callHomeEventManager;
}
/**
* Set the LicenseManager
*/
@Autowired
public void setLicenseManager(LicenseManager licenseManager) {
_licenseManager = licenseManager;
}
/**
* Set the CallHomeEventsFacade.
*
* @param callHomeEventsFacade
*/
@Autowired
public void setCallHomeEventsFacace(CallHomeEventsFacade callHomeEventsFacade) {
_callHomeEventsFacade = callHomeEventsFacade;
}
}