/*************************************************************************
* (c) Copyright 2017 Hewlett Packard Enterprise Development Company LP
*
* 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/.
************************************************************************/
package com.eucalyptus.portal.instanceusage;
import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous;
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
import com.amazonaws.services.simpleworkflow.flow.core.Promises;
import com.amazonaws.services.simpleworkflow.flow.core.TryCatchFinally;
import com.eucalyptus.component.annotation.ComponentPart;
import com.eucalyptus.portal.BillingProperties;
import com.eucalyptus.portal.common.Portal;
import com.eucalyptus.portal.workflow.BillingWorkflowState;
import com.eucalyptus.portal.workflow.InstanceLogActivitiesClient;
import com.eucalyptus.portal.workflow.InstanceLogActivitiesClientImpl;
import com.eucalyptus.portal.workflow.InstanceLogWorkflow;
import com.eucalyptus.simpleworkflow.common.client.Hourly;
import com.google.common.collect.Lists;
import org.apache.log4j.Logger;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Hourly(InstanceLogWorkflowStarter.class)
@ComponentPart(Portal.class)
public class InstanceLogWorkflowImpl implements InstanceLogWorkflow {
private static Logger LOG =
Logger.getLogger( InstanceLogWorkflowImpl.class );
final InstanceLogActivitiesClient client =
new InstanceLogActivitiesClientImpl();
private BillingWorkflowState state =
BillingWorkflowState.WORKFLOW_RUNNING;
TryCatchFinally task = null;
@Override
public void logInstanceHourly() {
task = new TryCatchFinally() {
@Override
protected void doTry() throws Throwable {
doLog();
}
@Override
protected void doCatch(Throwable e) throws Throwable {
waitCleanup(client.cleanupQueues());
state = BillingWorkflowState.WORKFLOW_FAILED;
LOG.error("Workflow logging instance usage has failed: ", e);
}
@Override
protected void doFinally() throws Throwable {
if (state == BillingWorkflowState.WORKFLOW_RUNNING)
state = BillingWorkflowState.WORKFLOW_SUCCESS;
}
};
}
@Asynchronous
public void doLog() {
final Promise<Map<String, String>> accountQueues =
client.distributeEvents(BillingProperties.INSTANCE_HOUR_SENSOR_QUEUE_NAME);
deleteQueues( accountQueues, processQueues(accountQueues) );
}
@Asynchronous
public Promise<List<Void>> processQueues(final Promise<Map<String, String>> futureQueues) {
final Map<String, String> queues = futureQueues.get();
final List<Promise<Void>> result = Lists.newArrayList();
Promise<Void> run = Promise.Void();
for (final String accountId : queues.keySet()) {
final String queueName = queues.get(accountId);
run = client.persist(
Promise.asPromise(accountId),
Promise.asPromise(queueName),
run); // persist is serialized
result.add(run);
}
return Promises.listOfPromisesToPromise(result);
}
@Asynchronous
public void deleteQueues(final Promise<Map<String, String>> futureQueues, Promise<List<Void>> processed) {
final List<String> queues = futureQueues.get().values().stream()
.collect(Collectors.toList());
waitFor(client.deleteQueues(queues));
}
@Asynchronous
void waitFor(final Promise<Void> task) {
LOG.debug("Finished writing instance hour records");
}
@Asynchronous
void waitCleanup(final Promise<Void> task) { LOG.error("Failed writing instance hour records"); }
@Override
public BillingWorkflowState getState() {
return this.state;
}
}