/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.server.operation;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.clientapi.server.operation.OperationServerService;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.operation.OperationHistory;
import org.rhq.core.domain.operation.OperationRequestStatus;
import org.rhq.core.domain.operation.ResourceOperationHistory;
import org.rhq.core.util.exception.ExceptionPackage;
import org.rhq.enterprise.server.util.LookupUtil;
/**
* This is the remote POJO implementation that takes in messages from the agent saying the agent finished invoking a
* particular operation on a managed resource. The agent will notify the server of either:
*
* <ul>
* <li>an operation successfully completed</li>
* <li>an operation was invoked but failed</li>
* <li>an operation was invoked but canceled</li>
* <li>an operation was invoked but timed out before completing</li>
* </ul>
*
* @author John Mazzitelli
*/
public class OperationServerServiceImpl implements OperationServerService {
private static final Log LOG = LogFactory.getLog(OperationServerServiceImpl.class);
public void operationCanceled(String jobId, Configuration result, ExceptionPackage error, long invocationTime,
long completionTime) {
if (LOG.isDebugEnabled()) {
LOG.debug("Operation invocation [" + jobId + "] was canceled [" + error + "] "
+ getFromStartToEndTimestampString(invocationTime, completionTime));
}
try {
Subject superuser = LookupUtil.getSubjectManager().getOverlord();
OperationManagerLocal operationManager = LookupUtil.getOperationManager();
ResourceOperationHistory history = null;
history = (ResourceOperationHistory) operationManager.getOperationHistoryByJobId(superuser, jobId);
// I think this will only ever occur if the server-side timed this out but the long running
// operation finally got back to us afterwards. We will still go ahead and
// persist the failure data because, obviously, the operation really didn't time out.
// I think, in reality, this condition will never occur (since the server-side will only ever
// timeout ridiculously long-lived operations, which is typically only when an agent shutdown occurred).
if (history.getStatus() != OperationRequestStatus.INPROGRESS) {
LOG.debug("Was told an operation was canceled but, curiously, it was not in progress: " + "job-id=["
+ jobId + "], op-history=[" + history + "]");
}
if (error != null) {
history.setErrorMessage(error.getStackTraceString());
} else {
history.setErrorMessage("Operation was canceled at " + new Date(completionTime));
}
history.setResults(result);
history.setStatus(OperationRequestStatus.CANCELED);
operationManager.updateOperationHistory(superuser, history);
operationManager.checkForCompletedGroupOperation(history.getId());
} catch (Exception e) {
LOG.error("Failed to update history from canceled operation, jobId=[" + jobId + "]. Cause: " + e, e);
LOG.error("The canceled operation [" + jobId + "] had an error of: "
+ ((error != null) ? error.getStackTraceString() : "?"));
}
}
public void operationFailed(String jobId, Configuration result, ExceptionPackage error, long invocationTime,
long completionTime) {
if (LOG.isDebugEnabled()) {
LOG.debug("Operation invocation [" + jobId + "] failed with error [" + error + "] "
+ getFromStartToEndTimestampString(invocationTime, completionTime));
}
try {
Subject superuser = LookupUtil.getSubjectManager().getOverlord();
OperationManagerLocal operationManager = LookupUtil.getOperationManager();
ResourceOperationHistory history = null;
history = (ResourceOperationHistory) operationManager.getOperationHistoryByJobId(superuser, jobId);
// I think this will only ever occur if the server-side timed this out but the long running
// operation finally got back to us afterwards. We will still go ahead and
// persist the failure data because, obviously, the operation really didn't time out.
// I think, in reality, this condition will never occur (since the server-side will only ever
// timeout ridiculously long-lived operations, which is typically only when an agent shutdown occurred).
if (history.getStatus() != OperationRequestStatus.INPROGRESS) {
LOG.debug("Was told an operation failed but, curiously, it was not in progress: " + "job-id=[" + jobId
+ "], op-history=[" + history + "]");
}
if (error != null) {
history.setErrorMessage(error.getStackTraceString());
} else {
history.setErrorMessage("Failed for an unknown reason at " + new Date(completionTime));
}
history.setResults(result);
history.setStatus(OperationRequestStatus.FAILURE);
operationManager.updateOperationHistory(superuser, history);
operationManager.checkForCompletedGroupOperation(history.getId());
} catch (Exception e) {
LOG.error("Failed to update history from failed operation, jobId=[" + jobId + "]. Cause: " + e, e);
LOG.error("The failed operation [" + jobId + "] had an error of: "
+ ((error != null) ? error.getStackTraceString() : "?"));
}
}
public void operationSucceeded(String jobId, Configuration result, long invocationTime, long completionTime) {
LOG.debug("Operation invocation [" + jobId + "] succeeded "
+ getFromStartToEndTimestampString(invocationTime, completionTime));
try {
Subject superuser = LookupUtil.getSubjectManager().getOverlord();
OperationManagerLocal operationManager = LookupUtil.getOperationManager();
ResourceOperationHistory history;
history = (ResourceOperationHistory) operationManager.getOperationHistoryByJobId(superuser, jobId);
// I think this will only ever occur if the server-side timed this out but the long running
// operation finally got back to us afterwards. We will still go ahead and
// persist the success data because, obviously, the operation really didn't time out.
// I think, in reality, this condition will never occur (since the server-side will only ever
// timeout ridiculously long-lived operations, which is typically only when an agent shutdown occurred).
if (history.getStatus() != OperationRequestStatus.INPROGRESS) {
LOG.debug("Was told an operation succeeded but, curiously, it was not in progress: " + "job-id=["
+ jobId + "], op-history=[" + history + "]");
}
history.setErrorMessage(null);
history.setResults(result);
history.setStatus(OperationRequestStatus.SUCCESS);
operationManager.updateOperationHistory(superuser, history);
operationManager.checkForCompletedGroupOperation(history.getId());
} catch (Exception e) {
LOG.error("Failed to update history from successful operation, jobId=[" + jobId + "]. Cause: " + e, e);
LOG.error("The successful operation [" + jobId + "] had results of: " + result);
}
}
public void operationTimedOut(String jobId, long invocationTime, long timeoutTime) {
LOG.debug("Operation invocation [" + jobId + "] failed due to a timeout "
+ getFromStartToEndTimestampString(invocationTime, timeoutTime));
try {
Subject superuser = LookupUtil.getSubjectManager().getOverlord();
OperationManagerLocal operationManager = LookupUtil.getOperationManager();
OperationHistory history = operationManager.getOperationHistoryByJobId(superuser, jobId);
if (history.getStatus() == OperationRequestStatus.INPROGRESS) {
history.setErrorMessage("Timed out");
history.setStatus(OperationRequestStatus.FAILURE);
operationManager.updateOperationHistory(superuser, history);
operationManager.checkForCompletedGroupOperation(history.getId());
} else {
// if the operation was not in progress, the server side probably already timed it out
LOG.warn("Was told to timeout an operation history but it was not in progress: " + "job-id=[" + jobId
+ "], op-history=[" + history + "]");
}
} catch (Exception e) {
LOG.error("Failed to update history from timed out operation, jobId=[" + jobId + "]. Cause: " + e, e);
}
}
private String getFromStartToEndTimestampString(long startTime, long endTime) {
Date startDate = new Date(startTime);
Date endDate = new Date(endTime);
return "(from " + startDate + " to " + endDate + ")";
}
}