package org.ovirt.engine.api.restapi.resource;
import java.net.URI;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.ovirt.engine.api.common.util.LinkHelper;
import org.ovirt.engine.api.common.util.StatusUtils;
import org.ovirt.engine.api.model.Action;
import org.ovirt.engine.api.model.BaseResource;
import org.ovirt.engine.api.model.Host;
import org.ovirt.engine.api.model.CreationStatus;
import org.ovirt.engine.api.resource.ActionResource;
import org.ovirt.engine.core.common.action.VdcActionParametersBase;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.queries.GetVdsByNameParameters;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.compat.Guid;
public abstract class AbstractBackendActionableResource <R extends BaseResource, Q /* extends IVdcQueryable */ >
extends AbstractBackendSubResource<R, Q> {
public AbstractBackendActionableResource(String id, Class<R> modelType, Class<Q> entityType, String... subCollections) {
super(id, modelType, entityType, subCollections);
}
/**
* Perform an action, managing asynchrony and returning an appropriate
* response.
*
* @param uriInfo wraps the URI for the current request
* @param task the backend task
* @param params the task parameters
* @param action action representation
* @return
*/
protected Response doAction(final VdcActionType task, final VdcActionParametersBase params, final Action action) {
awaitGrace(action);
try {
VdcReturnValueBase actionResult = doAction(task, params);
if (actionResult.getHasAsyncTasks()) {
if (expectBlocking(action)) {
CreationStatus status = awaitCompletion(actionResult);
return actionStatus(status, action);
} else {
return actionAsync(actionResult, action);
}
} else {
return actionSuccess(action);
}
} catch (Exception e) {
return handleError(e, action);
}
}
protected void awaitGrace(Action action) {
if (action.isSetGracePeriod() && action.getGracePeriod().isSetExpiry()) {
delay(action.getGracePeriod().getExpiry());
}
}
protected boolean expectBlocking(Action action) {
return action.isSetAsync() && !action.isAsync();
}
public ActionResource getActionSubresource(String action, String oid) {
// redirect back to the target resource if action no longer cached
// if not getActionSubresource() not overridden in resource sub-class
// (in which case async actions are not supported, and the action
// resource should never be queried)
//
return new ActionResource() {
@Override
public Response get() {
URI uri = URI.create(LinkHelper.addLinks(getUriInfo(), newModel(id)).getHref());
Response.Status status = Response.Status.MOVED_PERMANENTLY;
return Response.status(status).location(uri).build();
}
@Override
public Action getAction() {
return null;
}
};
}
protected Guid getHostId(Host host) {
return host.isSetId()
? new Guid(host.getId())
: getEntity(VDS.class,
VdcQueryType.GetVdsByName,
new GetVdsByNameParameters(host.getName()),
host.getName()).getvds_id();
}
protected Guid getHostId(Action action) {
return getHostId(action.getHost());
}
protected Response handleError(Exception e, Action action) {
try {
return handleError(e, false);
} catch (WebFaultException wfe) {
action.setFault(wfe.getFault());
return actionFailure(action, wfe);
} catch (WebApplicationException wae) {
return actionFailure(action, wae);
}
}
protected Response actionFailure(Action action, WebApplicationException wae) {
action.setStatus(StatusUtils.create(CreationStatus.FAILED));
return Response.fromResponse(wae.getResponse()).entity(action).build();
}
protected Response actionSuccess(Action action) {
action.setStatus(StatusUtils.create(CreationStatus.COMPLETE));
return Response.ok().entity(action).build();
}
protected Response actionStatus(CreationStatus status, Action action) {
action.setStatus(StatusUtils.create(status));
return Response.ok().entity(action).build();
}
protected Response actionAsync(VdcReturnValueBase actionResult, Action action) {
action.setAsync(true);
String ids = asString(actionResult.getTaskIdList());
action.setId(ids);
action.setHref(UriBuilder.fromPath(getPath(uriInfo)).path(ids).build().toString());
String path = getPath(uriInfo);
addOrUpdateLink(action, "parent", path.substring(0, path.lastIndexOf("/")));
addOrUpdateLink(action, "replay", path);
action.setStatus(StatusUtils.create(getAsynchronousStatus(actionResult)));
return Response.status(ACCEPTED_STATUS).entity(action).build();
}
private String getPath(UriInfo uriInfo) {
return LinkHelper.combine(uriInfo.getBaseUri().getPath(), uriInfo.getPath());
}
}