package com.sequenceiq.cloudbreak.orchestrator.yarn.poller;
import static com.sequenceiq.cloudbreak.orchestrator.yarn.api.YarnResourceConstants.ONE_SECOND;
import static com.sequenceiq.cloudbreak.orchestrator.yarn.api.YarnResourceConstants.RETRIES;
import java.net.MalformedURLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sequenceiq.cloudbreak.orchestrator.exception.CloudbreakOrchestratorException;
import com.sequenceiq.cloudbreak.orchestrator.exception.CloudbreakOrchestratorFailedException;
import com.sequenceiq.cloudbreak.orchestrator.yarn.api.YarnResourceConstants;
import com.sequenceiq.cloudbreak.orchestrator.yarn.client.YarnClient;
import com.sequenceiq.cloudbreak.orchestrator.yarn.client.YarnHttpClient;
import com.sequenceiq.cloudbreak.orchestrator.yarn.model.core.ApplicationState;
import com.sequenceiq.cloudbreak.orchestrator.yarn.model.core.Container;
import com.sequenceiq.cloudbreak.orchestrator.yarn.model.core.ContainerState;
import com.sequenceiq.cloudbreak.orchestrator.yarn.model.request.ApplicationDetailRequest;
import com.sequenceiq.cloudbreak.orchestrator.yarn.model.response.ApplicationDetailResponse;
import com.sequenceiq.cloudbreak.orchestrator.yarn.model.response.ResponseContext;
public class YarnApplicationPoller {
private static final Logger LOGGER = LoggerFactory.getLogger(YarnApplicationPoller.class);
public YarnApplicationPoller() { }
public void waitForApplicationStart(String appName, String apiEndpoint) throws CloudbreakOrchestratorException, MalformedURLException {
YarnClient dashHttpClient = new YarnHttpClient(apiEndpoint);
for (int i = 1; i <= RETRIES; i++) {
// Make the request
ResponseContext responseContext = dashHttpClient.getApplicationDetail(getApplicationDetailRequest(appName));
// If 404, application isn't ready, sleep
if (responseContext.getStatusCode() == YarnResourceConstants.HTTP_NOT_FOUND) {
handle404(appName, responseContext);
}
// If 200, check application state to ensure RUNNING
if (responseContext.getStatusCode() == YarnResourceConstants.HTTP_SUCCESS) {
if (null != responseContext.getResponseObject()) {
ApplicationDetailResponse applicationDetailResponse = (ApplicationDetailResponse) responseContext.getResponseObject();
// Validate the application is "RUNNING"
if (!applicationDetailResponse.getState().equals(ApplicationState.READY.name())) {
LOGGER.debug(String.format("Application %s not ready, in %s state, sleeping 1000 ms", appName, applicationDetailResponse.getState()));
sleep();
} else {
// Validate the container is running
if (applicationDetailResponse.getContainers().size() > 0) {
Container appContainer = applicationDetailResponse.getContainers().get(0);
if (!appContainer.getState().equals(ContainerState.READY.name())) {
String msg = String.format("Application %s not ready, in %s state, sleeping 1000 ms",
appName, applicationDetailResponse.getState());
LOGGER.debug(msg);
sleep();
} else {
String msg = String.format("Application %s has now successfully started, in %s state",
appName, applicationDetailResponse.getState());
LOGGER.debug(msg);
break;
}
}
}
}
}
if (i == RETRIES) {
String msg = String.format("ERROR: %s did not start in %d retries", appName, RETRIES);
throw new CloudbreakOrchestratorFailedException(msg);
}
}
}
private void handle404(String appName, ResponseContext responseContext) {
String msg = String.format("Application %s not ready, received %d response, sleeping 1000 ms", appName, responseContext.getStatusCode());
LOGGER.debug(msg);
sleep();
}
private void sleep() {
try {
Thread.sleep(ONE_SECOND);
} catch (InterruptedException e) {
}
}
private ApplicationDetailRequest getApplicationDetailRequest(String appName) {
ApplicationDetailRequest applicationDetailRequest = new ApplicationDetailRequest();
applicationDetailRequest.setName(appName);
return applicationDetailRequest;
}
}