@Override public Service createServiceInstance() { return new ClosureService(driverRegistry, maintenanceTimeout); }
private void processExecution(Operation op, Closure closure, ClosureDescription taskDef) { switch (closure.state) { case CREATED: case CANCELLED: handleReadyState(op, closure, taskDef); break; case STARTED: handledLeasedState(op, closure); break; case FINISHED: case FAILED: handleDoneState(op, closure); break; default: logWarning("Unsupported closure lease state: %s", closure.state); } }
private void processMaintenance(Operation op, Closure closure, ClosureDescription taskDef) { if (closure == null) { logWarning("Skip maintenance call..."); return; } if (isTaskExpired(closure, taskDef)) { completeCancelTask(taskDef, closure); } op.complete(); }
private void moveToCompleteState(Closure currentState) { Closure completedState = new Closure(); completedState.state = TaskState.TaskStage.FINISHED; completedState.closureSemaphore = currentState.closureSemaphore; completedState.inputs = currentState.inputs; final Map outputs = new HashMap(); completedState.inputs.forEach((k, v) -> { outputs.put(k, v); }); completedState.outputs = outputs; getHost().schedule(() -> sendSelfPatch(completedState), 3, TimeUnit.SECONDS); } }
protected void updateRequestStatus(Closure closure) { ClosureTaskState state = fromClosure(closure); String requestStatusLink = ManagementUriParts.REQUEST_STATUS + "/" + getSelfId(); sendRequest(Operation .createGet(getHost(), requestStatusLink) .setCompletion((op, ex) -> { if (ex != null) { if (op.getStatusCode() == 404) { createRequestTracker(state); } else { logWarning("Unable to update request status for:" + closure .documentSelfLink, ex); } } else { state.requestTrackerLink = requestStatusLink; updateRequestTracker(state, ClosureProps.RETRIES_COUNT); } })); }
@Override public void handleStart(Operation startOp) { if (!hasBody(startOp)) { return; } Closure closure = startOp.getBody(Closure.class); logInfo("Closure state: %s, closure definition: %s", closure.state, closure.descriptionLink); if (isNotValid(startOp, closure)) { return; } if (closure.state == TaskStage.CREATED || closure.state == TaskStage.CANCELLED) { initializeTask(startOp, closure); } else { this.setState(startOp, closure); startOp.setBody(closure).complete(); } }
private void createRequestTracker(ClosureTaskState state) { sendRequest(Operation.createPost(this, ManagementUriParts.REQUEST_STATUS) .setBodyNoCloning(fromTask(state)) .setCompletion((o, e) -> { if (e != null) { logWarning("Failed to create request tracker for: " + state.documentSelfLink, e); return; } state.requestTrackerLink = o.getBody(TaskStatusState.class).documentSelfLink; logInfo("Created request tracker: %s", state.requestTrackerLink); updateRequestTracker(state, ClosureProps.RETRIES_COUNT); })); }
protected void notifyCallerService(Closure closureState) { if (closureState.serviceTaskCallback.isEmpty()) { return; } if (closureState.serviceTaskCallback.isExternal()) { sendRequestStateToExternalUrl(closureState.serviceTaskCallback.serviceSelfLink, closureState); } else { ClosureCallbackCompleteResponse callbackResponse = new ClosureCallbackCompleteResponse(); if (closureState.state == TaskStage.FINISHED) { callbackResponse.copy(closureState.serviceTaskCallback.getFinishedResponse()); } else { callbackResponse .copy(closureState.serviceTaskCallback.getFailedResponse(new Exception( closureState.errorMsg))); } sendRequest( Operation.createPatch(this, closureState.serviceTaskCallback.serviceSelfLink) .setBody(callbackResponse) .setCompletion((o, e) -> { if (e != null) { logWarning("Notifying parent task %s failed: %s", o.getUri(), Utils.toString(e)); } })); } }
protected ClosureRequestStatus fromTask(ClosureTaskState state) { ClosureRequestStatus taskStatus = new ClosureRequestStatus(); taskStatus.documentSelfLink = getSelfId(); taskStatus.phase = CLOSURE_EXECUTION_PHASE; taskStatus.taskInfo = state.taskInfo; taskStatus.subStage = state.taskSubStage.name(); taskStatus.tenantLinks = state.tenantLinks; if (state.customProperties != null) { taskStatus.eventLogLink = state.customProperties.get( TaskStatusState.FIELD_NAME_EVENT_LOG_LINK); } // task progress is the current stage divided by number of normal stages (not including the // error one) taskStatus.progress = 100 * state.taskSubStage.ordinal() / (state.taskSubStage.getClass().getEnumConstants().length - 2); if (taskStatus.progress > 100) { // reached error state taskStatus.progress = 100; } taskStatus.requestProgressByComponent = state.requestProgressByComponent; taskStatus.resourceLinks = state.resourceLinks; taskStatus.name = state.name; return taskStatus; }
private void completeCancelTask(ClosureDescription closureDesc, Closure closure) { String errorMsg = "Configured timeout of [%s] seconds has expired. Closure %s is" + " cancelled."; logInfo(errorMsg, closureDesc.resources.timeoutSeconds, closure.documentSelfLink); closure.state = TaskStage.CANCELLED; closure.errorMsg = String.format(errorMsg, closureDesc.resources.timeoutSeconds, closure.documentSelfLink); closure.endTimeMillis = System.currentTimeMillis(); sendSelfPatch(closure); getExecutionDriver(closureDesc) .cleanClosure(closure, (error) -> logWarning("Unable to clean resources for %s", closure.documentSelfLink)); }
private void initializeTask(Operation post, Closure closure) { sendRequest(Operation .createGet(this, closure.descriptionLink) .setCompletion((op, ex) -> { if (ex != null) { logWarning("Failed to fetch closure definition closure! Reason: %s", ex.getMessage()); post.fail(new Exception("Unable to fetch script source.")); } else { initTask(closure, op); this.setState(post, closure); post.setBody(closure).complete(); } })); }
protected void sendSelfPatch(Closure body) { sendRequest(Operation .createPatch(getUri()) .setBody(body) .setCompletion((o, ex) -> { if (ex != null) { logWarning("Self patch failed: %s", Utils.toString(ex)); } })); }
private void verifyPatchRequest(Closure currentState, Closure requestedState) { switch (currentState.state) { case CREATED: case CANCELLED: verifyReadyPatch(currentState, requestedState); break; case STARTED: verifyLeasedPatch(currentState, requestedState); break; case FINISHED: case FAILED: break; default: throw new IllegalArgumentException( "Unexpected state change requested: " + requestedState.state + " was: " + currentState.state); } }
private boolean isTaskExpired(Closure closure, ClosureDescription taskDef) { if (closure.state != TaskStage.STARTED) { return false; } if (taskDef.resources == null) { logWarning("No constraints constraints bound to closure."); } if (closure.lastLeasedTimeMillis == null) { return false; } long timeElapsed = System.currentTimeMillis() - closure.lastLeasedTimeMillis; if (timeElapsed > (taskDef.resources.timeoutSeconds * 1000)) { logInfo("Timeout elapsed=%s, timeout=%s of closure=%s", timeElapsed, taskDef.resources.timeoutSeconds * 1000, closure.documentSelfLink); return true; } return false; }
private void handledLeasedState(Operation op, Closure closure) { logInfo("Closure is already being executed by : %s", closure.documentSelfLink); op.setStatusCode(Operation.STATUS_CODE_BAD_REQUEST); op.fail(new IllegalArgumentException( String.format("Closure has already been executed: %s", closure.documentSelfLink))); }
private void moveToStartedState(Closure currentState) { Closure startedState = new Closure(); startedState.state = TaskState.TaskStage.STARTED; startedState.closureSemaphore = currentState.closureSemaphore; getHost().schedule(() -> sendSelfPatch(startedState), 1, TimeUnit.SECONDS); }
private void handleDoneState(Operation op, Closure closure) { logInfo("Closure has already been executed: %s", closure.documentSelfLink); op.setStatusCode(Operation.STATUS_CODE_BAD_REQUEST); op.fail(new IllegalArgumentException( String.format("Closure has already been executed: %s", closure.documentSelfLink))); }
@Test public void inspectImageClosureTest() { final Object[] errors = { null }; Closure closure = new Closure(); dockerDriver.inspectImage("test_image", "image_link", (error) -> errors[0] = error ); assertNull(errors[0]); }
@Test public void inspectImageNoImageLinkTest() { final Object[] errors = { null }; Closure closure = new Closure(); dockerDriver.inspectImage("test_image", null, (error) -> errors[0] = error ); assertNotNull(errors[0]); }
@Test public void cleanClosureNoLinkTest() { final Object[] errors = { null }; Closure closure = new Closure(); dockerDriver.cleanClosure(closure, (error) -> errors[0] = error ); assertNotNull(errors[0]); }