package com.sequenceiq.cloudbreak.service.events;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specifications;
import org.springframework.stereotype.Service;
import com.sequenceiq.cloudbreak.domain.CloudbreakEvent;
import com.sequenceiq.cloudbreak.domain.Cluster;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.repository.CloudbreakEventRepository;
import com.sequenceiq.cloudbreak.repository.CloudbreakEventSpecifications;
import com.sequenceiq.cloudbreak.repository.StackRepository;
import reactor.bus.Event;
import reactor.bus.EventBus;
import reactor.bus.selector.Selectors;
@Service
public class DefaultCloudbreakEventService implements CloudbreakEventService {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCloudbreakEventService.class);
private static final String CLOUDBREAK_EVENT = "CLOUDBREAK_EVENT";
@Inject
private StackRepository stackRepository;
@Inject
private CloudbreakEventRepository eventRepository;
@Inject
private EventBus reactor;
@Inject
private CloudbreakEventHandler cloudbreakEventHandler;
@PostConstruct
public void setup() {
reactor.on(Selectors.$(CLOUDBREAK_EVENT), cloudbreakEventHandler);
}
@Override
public void fireCloudbreakEvent(Long stackId, String eventType, String eventMessage) {
CloudbreakEventData eventData = new CloudbreakEventData(stackId, eventType, eventMessage);
LOGGER.info("Firing Cloudbreak event: {}", eventData);
Event reactorEvent = Event.wrap(eventData);
reactor.notify(CLOUDBREAK_EVENT, reactorEvent);
}
@Override
public void fireCloudbreakInstanceGroupEvent(Long stackId, String eventType, String eventMessage, String instanceGroupName) {
InstanceGroupEventData eventData = new InstanceGroupEventData(stackId, eventType, eventMessage, instanceGroupName);
LOGGER.info("Fireing cloudbreak event: {}", eventData);
Event reactorEvent = Event.wrap(eventData);
reactor.notify(CLOUDBREAK_EVENT, reactorEvent);
}
@Override
public CloudbreakEvent createStackEvent(CloudbreakEventData eventData) {
LOGGER.debug("Creating stack event from: {}", eventData);
String instanceGroupName = getInstanceGroupNameFromEvent(eventData);
Stack stack = stackRepository.findById(eventData.getEntityId());
CloudbreakEvent stackEvent = createStackEvent(stack, eventData.getEventType(), eventData.getEventMessage(), instanceGroupName);
stackEvent = eventRepository.save(stackEvent);
LOGGER.info("Created stack event: {}", stackEvent);
return stackEvent;
}
private String getInstanceGroupNameFromEvent(CloudbreakEventData eventData) {
String instanceGroup = null;
if (eventData instanceof InstanceGroupEventData) {
instanceGroup = ((InstanceGroupEventData) eventData).getInstanceGroupName();
}
return instanceGroup;
}
@Override
@SuppressWarnings("unchecked")
public List<CloudbreakEvent> cloudbreakEvents(String owner, Long since) {
List<CloudbreakEvent> events;
if (null == since) {
events = eventRepository.findAll(CloudbreakEventSpecifications.eventsForUser(owner));
} else {
events = eventRepository.findAll(Specifications
.where(CloudbreakEventSpecifications.eventsForUser(owner))
.and(CloudbreakEventSpecifications.eventsSince(since)));
}
return null != events ? events : Collections.EMPTY_LIST;
}
private CloudbreakEvent createStackEvent(Stack stack, String eventType, String eventMessage, String instanceGroupName) {
CloudbreakEvent stackEvent = new CloudbreakEvent();
stackEvent.setEventTimestamp(Calendar.getInstance().getTime());
stackEvent.setEventMessage(eventMessage);
stackEvent.setEventType(eventType);
stackEvent.setOwner(stack.getOwner());
stackEvent.setAccount(stack.getAccount());
stackEvent.setStackId(stack.getId());
stackEvent.setStackStatus(stack.getStatus());
stackEvent.setStackName(stack.getName());
stackEvent.setNodeCount(stack.getRunningInstanceMetaData().size());
stackEvent.setRegion(stack.getRegion());
stackEvent.setAvailabilityZone(stack.getAvailabilityZone());
stackEvent.setCloud(stack.cloudPlatform());
populateClusterData(stackEvent, stack);
if (instanceGroupName != null) {
stackEvent.setInstanceGroup(instanceGroupName);
}
return stackEvent;
}
private void populateClusterData(CloudbreakEvent stackEvent, Stack stack) {
Cluster cluster = stack.getCluster();
if (cluster != null) {
stackEvent.setClusterStatus(cluster.getStatus());
if (cluster.getBlueprint() != null) {
stackEvent.setBlueprintId(cluster.getBlueprint().getId());
stackEvent.setBlueprintName(cluster.getBlueprint().getBlueprintName());
}
stackEvent.setClusterId(cluster.getId());
stackEvent.setClusterName(cluster.getName());
} else {
LOGGER.debug("No cluster data available for the stack: {}", stack.getId());
}
}
}