package com.sequenceiq.cloudbreak.orchestrator.yarn.handler; import static com.sequenceiq.cloudbreak.orchestrator.yarn.api.YarnResourceConstants.NON_AGENT_CPUS; import static com.sequenceiq.cloudbreak.orchestrator.yarn.api.YarnResourceConstants.NON_AGENT_MEMORY; import static com.sequenceiq.cloudbreak.orchestrator.yarn.api.YarnResourceConstants.UNLIMITED; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.sequenceiq.cloudbreak.orchestrator.exception.CloudbreakOrchestratorFailedException; import com.sequenceiq.cloudbreak.orchestrator.model.ContainerConfig; import com.sequenceiq.cloudbreak.orchestrator.model.ContainerConstraint; import com.sequenceiq.cloudbreak.orchestrator.model.OrchestrationCredential; import com.sequenceiq.cloudbreak.orchestrator.yarn.api.ComponentType; import com.sequenceiq.cloudbreak.orchestrator.yarn.api.Entrypoint; import com.sequenceiq.cloudbreak.orchestrator.yarn.client.YarnClient; import com.sequenceiq.cloudbreak.orchestrator.yarn.client.YarnHttpClient; import com.sequenceiq.cloudbreak.orchestrator.yarn.model.core.Artifact; import com.sequenceiq.cloudbreak.orchestrator.yarn.model.core.YarnComponent; import com.sequenceiq.cloudbreak.orchestrator.yarn.model.core.Resource; import com.sequenceiq.cloudbreak.orchestrator.yarn.model.request.CreateApplicationRequest; import com.sequenceiq.cloudbreak.orchestrator.yarn.model.response.ApplicationErrorResponse; import com.sequenceiq.cloudbreak.orchestrator.yarn.model.response.ResponseContext; import com.sequenceiq.cloudbreak.orchestrator.yarn.util.ApplicationUtils; @Service public class ApplicationSubmissionHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationSubmissionHandler.class); private static final int ONE = 1; @Inject private ApplicationUtils applicationUtils; private String ambariDbHostname; private String ambariServerHostname; public void submitApplication(ContainerConfig config, OrchestrationCredential cred, ContainerConstraint constraint, int componentNumber) throws CloudbreakOrchestratorFailedException { // Set Ambari DB hostname, if available if (ComponentType.AMBARIDB.equals(applicationUtils.getComponentType(constraint))) { ambariDbHostname = applicationUtils.getComponentHostName(constraint, cred, componentNumber); } // Set Ambari Server hostname, if available if (ComponentType.AMBARISERVER.equals(applicationUtils.getComponentType(constraint))) { ambariServerHostname = applicationUtils.getComponentHostName(constraint, cred, componentNumber); } // Application level attributes String applicationName = applicationUtils.getApplicationName(constraint, componentNumber); CreateApplicationRequest createApplicationRequest = new CreateApplicationRequest(); createApplicationRequest.setName(applicationName); createApplicationRequest.setQueue(config.getQueue()); createApplicationRequest.setLifetime(UNLIMITED); // Define the artifact (docker image) for the component Artifact artifact = new Artifact(); artifact.setId(getDockerImageName(config)); artifact.setType("DOCKER"); // Define the resources for the component Resource resource = new Resource(); resource.setCpus(getCpusForContainerType(constraint)); resource.setMemory(getMemForContainerType(constraint)); // Add the component List<YarnComponent> components = new ArrayList<>(); YarnComponent component = new YarnComponent(); component.setName(applicationUtils.getComponentName(constraint, componentNumber)); component.setNumberOfContainers(ONE); component.setLaunchCommand(getFullEntrypoint(constraint, cred, componentNumber)); component.setArtifact(artifact); component.setDependencies(new ArrayList<>()); component.setResource(resource); component.setRunPrivilegedContainer(true); components.add(component); createApplicationRequest.setComponents(components); // Submit the request YarnClient yarnHttpClient = new YarnHttpClient(cred.getApiEndpoint()); try { submitCreateApplicationRequest(createApplicationRequest, yarnHttpClient); } catch (Exception e) { throw new CloudbreakOrchestratorFailedException(e); } } private void submitCreateApplicationRequest(CreateApplicationRequest createApplicationRequest, YarnClient yarnHttpClient) throws CloudbreakOrchestratorFailedException { try { ResponseContext createAppResponseContext = yarnHttpClient.createApplication(createApplicationRequest); if (createAppResponseContext.getResponseError() != null) { ApplicationErrorResponse applicationErrorResponse = createAppResponseContext.getResponseError(); String msg = String.format("ERROR: HTTP Return: %d Error: %s", createAppResponseContext.getStatusCode(), applicationErrorResponse.getDiagnostics()); LOGGER.debug(msg); throw new CloudbreakOrchestratorFailedException(msg); } } catch (Exception e) { throw new CloudbreakOrchestratorFailedException(e); } } private String getDockerImageName(ContainerConfig config) { return String.format("%s:%s", config.getName(), config.getVersion()); } private int getCpusForContainerType(ContainerConstraint constraint) throws CloudbreakOrchestratorFailedException { if (ComponentType.AMBARIAGENT.equals(applicationUtils.getComponentType(constraint))) { return constraint.getCpu().intValue(); } return NON_AGENT_CPUS; } private int getMemForContainerType(ContainerConstraint constraint) throws CloudbreakOrchestratorFailedException { if (ComponentType.AMBARIAGENT.equals(applicationUtils.getComponentType(constraint))) { return constraint.getMem().intValue(); } return NON_AGENT_MEMORY; } private String getFullEntrypoint(ContainerConstraint constraint, OrchestrationCredential cred, int componentNumber) throws CloudbreakOrchestratorFailedException { Entrypoint entryPoint = Entrypoint.valueOf(applicationUtils.getComponentType(constraint).name()); String fullEntryPoint = entryPoint.getEntryPoint(); // Pass the Ambari DB hostname to the Ambari Server entry point if (ComponentType.AMBARISERVER.equals(applicationUtils.getComponentType(constraint))) { return String.format("%s %s", entryPoint.getEntryPoint(), ambariDbHostname); } // Pass the Ambari Server hostname to the Ambari Agent entry point if (ComponentType.AMBARIAGENT.equals(applicationUtils.getComponentType(constraint))) { return String.format("%s %s %s", entryPoint.getEntryPoint(), ambariServerHostname, applicationUtils.getComponentHostName(constraint, cred, componentNumber)); } return fullEntryPoint; } }