/************************************************************************* * Copyright 2009-2016 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. ************************************************************************/ package com.eucalyptus.loadbalancing.workflow; import com.eucalyptus.simpleworkflow.common.client.Repeating; import org.apache.log4j.Logger; import com.amazonaws.services.simpleworkflow.flow.DecisionContextProvider; import com.amazonaws.services.simpleworkflow.flow.DecisionContextProviderImpl; import com.amazonaws.services.simpleworkflow.flow.WorkflowClock; import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous; import com.amazonaws.services.simpleworkflow.flow.core.AndPromise; import com.amazonaws.services.simpleworkflow.flow.core.Promise; import com.amazonaws.services.simpleworkflow.flow.core.TryCatchFinally; import com.eucalyptus.component.annotation.ComponentPart; import com.eucalyptus.loadbalancing.common.LoadBalancing; /** * @author Sang-Min Park (sangmin.park@hpe.com) * */ @ComponentPart(LoadBalancing.class) @Repeating(value = LoadBalancingServiceHealthCheckWorkflowStarter.class, sleepSeconds = 60, dependsOn = LoadBalancing.class) public class LoadBalancingServiceHealthCheckWorkflowImpl implements LoadBalancingServiceHealthCheckWorkflow { private static Logger LOG = Logger.getLogger( LoadBalancingServiceHealthCheckWorkflowImpl.class ); final LoadBalancingActivitiesClient client = new LoadBalancingActivitiesClientImpl(); private ElbWorkflowState state = ElbWorkflowState.WORKFLOW_RUNNING; TryCatchFinally task = null; private DecisionContextProvider contextProvider = new DecisionContextProviderImpl(); final WorkflowClock clock = contextProvider.getDecisionContext().getWorkflowClock(); private final int MAX_UPDATE_PER_WORKFLOW = 10; //// TODO: Make this configurable for scale private final int UPDATE_PERIOD_SEC = 60; @Override public void performServiceHealthCheck() { task = new TryCatchFinally() { @Override protected void doTry() throws Throwable { performServiceHealthCheckPeriodic(0); } @Override protected void doCatch(Throwable e) throws Throwable { state = ElbWorkflowState.WORKFLOW_FAILED; LOG.error("Workflow for updating ELB service state has failed: ", e); } @Override protected void doFinally() throws Throwable { if (state == ElbWorkflowState.WORKFLOW_RUNNING) state = ElbWorkflowState.WORKFLOW_SUCCESS; } }; } @Asynchronous void performServiceHealthCheckPeriodic(final int count, final Promise<?>... waitFor) { if (count >= MAX_UPDATE_PER_WORKFLOW) { return; } final Promise<Void> timer = startDaemonTimer(UPDATE_PERIOD_SEC); final Promise<Void> checkContinousWorkflows = client.runContinousWorkflows(); final Promise<Void> checkServo = client.checkServoInstances(checkContinousWorkflows); final Promise<Void> checkDns = client.checkServoInstanceDns(checkServo); final Promise<Void> checkServoElasticIp = client.checkServoElasticIp(checkDns); final Promise<Void> checkBackend = client.checkBackendInstances(checkServoElasticIp); final Promise<Void> cleanupServo = client.cleanupServoInstances(checkBackend); final Promise<Void> cleanupSecurityGroup = client.cleanupSecurityGroups(cleanupServo); final Promise<Void> recycleServo = client.recycleFailedServoInstances(cleanupSecurityGroup); performServiceHealthCheckPeriodic(count+1, new AndPromise(timer, recycleServo)); } @Asynchronous(daemon = true) private Promise<Void> startDaemonTimer(int seconds) { Promise<Void> timer = clock.createTimer(seconds); return timer; } @Override public ElbWorkflowState getState() { return state; } }