package com.sequenceiq.cloudbreak.core.flow2.chain;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.sequenceiq.cloudbreak.api.model.InstanceGroupType;
import com.sequenceiq.cloudbreak.api.model.InstanceMetadataType;
import com.sequenceiq.cloudbreak.cloud.event.Selectable;
import com.sequenceiq.cloudbreak.common.type.ScalingType;
import com.sequenceiq.cloudbreak.core.flow2.cluster.repair.ChangePrimaryGatewayEvent;
import com.sequenceiq.cloudbreak.core.flow2.event.ClusterAndStackDownscaleTriggerEvent;
import com.sequenceiq.cloudbreak.core.flow2.event.StackAndClusterUpscaleTriggerEvent;
import com.sequenceiq.cloudbreak.domain.HostGroup;
import com.sequenceiq.cloudbreak.domain.InstanceGroup;
import com.sequenceiq.cloudbreak.domain.InstanceMetaData;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.reactor.api.event.orchestration.ChangePrimaryGatewayTriggerEvent;
import com.sequenceiq.cloudbreak.reactor.api.event.orchestration.ClusterRepairTriggerEvent;
import com.sequenceiq.cloudbreak.repository.InstanceMetaDataRepository;
import com.sequenceiq.cloudbreak.service.hostgroup.HostGroupService;
import com.sequenceiq.cloudbreak.service.stack.StackService;
@Component
public class ClusterRepairFlowEventChainFactory implements FlowEventChainFactory<ClusterRepairTriggerEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(ClusterRepairFlowEventChainFactory.class);
@Inject
private StackService stackService;
@Inject
private HostGroupService hostGroupService;
@Inject
private InstanceMetaDataRepository instanceMetadataRepository;
@Override
public String initEvent() {
return FlowChainTriggers.CLUSTER_REPAIR_TRIGGER_EVENT;
}
@Override
public Queue<Selectable> createFlowTriggerEventQueue(ClusterRepairTriggerEvent event) {
Stack stack = stackService.getById(event.getStackId());
Queue<Selectable> flowChainTriggers = new ConcurrentLinkedDeque<>();
Map<String, List<String>> failedNodesMap = event.getFailedNodesMap();
for (Map.Entry<String, List<String>> failedNodes : failedNodesMap.entrySet()) {
HostGroup hostGroup = hostGroupService.getByClusterIdAndName(stack.getCluster().getId(), failedNodes.getKey());
InstanceGroup instanceGroup = hostGroup.getConstraint().getInstanceGroup();
if (instanceGroup.getInstanceGroupType() == InstanceGroupType.GATEWAY) {
if (instanceGroup.getNodeCount() <= 1) {
LOGGER.warn("Gateway instancegroup cannot be repaired if its nodecount is less or equal to 1.");
continue;
} else {
List<InstanceMetaData> primary = instanceMetadataRepository.findAllByInstanceGroup(instanceGroup).stream().filter(
imd -> failedNodes.getValue().contains(imd.getDiscoveryFQDN())
&& imd.getInstanceMetadataType() == InstanceMetadataType.GATEWAY_PRIMARY).collect(Collectors.toList());
if (!primary.isEmpty()) {
flowChainTriggers.add(new ChangePrimaryGatewayTriggerEvent(ChangePrimaryGatewayEvent.CHANGE_PRIMARY_GATEWAY_TRIGGER_EVENT.event(),
event.getStackId(), event.accepted()));
}
}
}
flowChainTriggers.add(new ClusterAndStackDownscaleTriggerEvent(FlowChainTriggers.FULL_DOWNSCALE_TRIGGER_EVENT, event.getStackId(),
failedNodes.getKey(), new HashSet<>(failedNodes.getValue()), ScalingType.DOWNSCALE_TOGETHER, event.accepted()));
if (!event.isRemoveOnly()) {
flowChainTriggers.add(new StackAndClusterUpscaleTriggerEvent(FlowChainTriggers.FULL_UPSCALE_TRIGGER_EVENT, event.getStackId(),
failedNodes.getKey(), failedNodes.getValue().size(), ScalingType.UPSCALE_TOGETHER));
}
}
return flowChainTriggers;
}
}