org.finra.herd.service.impl.EmrServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of herd-service Show documentation
Show all versions of herd-service Show documentation
This project contains the business service code. This is a classic service tier where business logic is defined along with it's associated
transaction management configuration.
/*
* Copyright 2015 herd contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.finra.herd.service.impl;
import java.util.Date;
import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.elasticmapreduce.model.Cluster;
import com.amazonaws.services.elasticmapreduce.model.ClusterStatus;
import com.amazonaws.services.elasticmapreduce.model.ClusterSummary;
import com.amazonaws.services.elasticmapreduce.model.ListInstanceFleetsResult;
import com.amazonaws.services.elasticmapreduce.model.Step;
import com.amazonaws.services.elasticmapreduce.model.StepSummary;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.finra.herd.core.HerdDateUtils;
import org.finra.herd.dao.EmrDao;
import org.finra.herd.dao.config.DaoSpringModuleConfig;
import org.finra.herd.dao.helper.EmrHelper;
import org.finra.herd.dao.helper.HerdStringHelper;
import org.finra.herd.dao.helper.JsonHelper;
import org.finra.herd.model.annotation.NamespacePermission;
import org.finra.herd.model.api.xml.EmrCluster;
import org.finra.herd.model.api.xml.EmrClusterCreateRequest;
import org.finra.herd.model.api.xml.EmrClusterDefinition;
import org.finra.herd.model.api.xml.EmrClusterDefinitionKey;
import org.finra.herd.model.api.xml.EmrMasterSecurityGroup;
import org.finra.herd.model.api.xml.EmrMasterSecurityGroupAddRequest;
import org.finra.herd.model.api.xml.EmrStep;
import org.finra.herd.model.api.xml.NamespacePermissionEnum;
import org.finra.herd.model.api.xml.StatusChangeReason;
import org.finra.herd.model.api.xml.StatusTimeline;
import org.finra.herd.model.dto.AwsParamsDto;
import org.finra.herd.model.dto.EmrClusterAlternateKeyDto;
import org.finra.herd.model.dto.EmrClusterCreateDto;
import org.finra.herd.model.jpa.EmrClusterDefinitionEntity;
import org.finra.herd.service.EmrService;
import org.finra.herd.service.helper.AlternateKeyHelper;
import org.finra.herd.service.helper.AwsServiceHelper;
import org.finra.herd.service.helper.EmrClusterDefinitionDaoHelper;
import org.finra.herd.service.helper.EmrStepHelper;
import org.finra.herd.service.helper.EmrStepHelperFactory;
import org.finra.herd.service.helper.NamespaceDaoHelper;
/**
* The EMR service implementation.
*/
@Service
@Transactional(value = DaoSpringModuleConfig.HERD_TRANSACTION_MANAGER_BEAN_NAME)
public class EmrServiceImpl implements EmrService
{
private static final Logger LOGGER = LoggerFactory.getLogger(EmrServiceImpl.class);
@Autowired
private AlternateKeyHelper alternateKeyHelper;
@Autowired
private AwsServiceHelper awsServiceHelper;
@Autowired
private EmrClusterDefinitionDaoHelper emrClusterDefinitionDaoHelper;
@Autowired
private EmrDao emrDao;
@Autowired
private EmrHelper emrHelper;
@Autowired
private EmrHelperServiceImpl emrHelperServiceImpl;
@Autowired
private EmrStepHelperFactory emrStepHelperFactory;
@Autowired
private HerdStringHelper herdStringHelper;
@Autowired
private JsonHelper jsonHelper;
@Autowired
private NamespaceDaoHelper namespaceDaoHelper;
/**
* {@inheritDoc}
*
* This implementation starts a new transaction.
*/
@NamespacePermission(fields = "#emrClusterAlternateKeyDto?.namespace", permissions = NamespacePermissionEnum.READ)
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EmrCluster getCluster(EmrClusterAlternateKeyDto emrClusterAlternateKeyDto, String emrClusterId, String emrStepId, boolean verbose, String accountId,
Boolean retrieveInstanceFleets) throws Exception
{
return getClusterImpl(emrClusterAlternateKeyDto, emrClusterId, emrStepId, verbose, accountId, retrieveInstanceFleets);
}
/**
* Gets details of an existing EMR Cluster.
*
* @param emrClusterAlternateKeyDto the EMR cluster alternate key
* @param emrClusterId the cluster id of the cluster to get details
* @param emrStepId the step id of the step to get details
* @param verbose parameter for whether to return detailed information
* @param accountId the optional AWS account that EMR cluster is running in
* @param retrieveInstanceFleets parameter for whether to retrieve instance fleets
*
* @return the EMR Cluster object with details.
*/
protected EmrCluster getClusterImpl(EmrClusterAlternateKeyDto emrClusterAlternateKeyDto, String emrClusterId, String emrStepId, boolean verbose,
String accountId, Boolean retrieveInstanceFleets)
{
AwsParamsDto awsParamsDto = emrHelper.getAwsParamsDtoByAccountId(accountId);
// Perform the request validation.
validateEmrClusterKey(emrClusterAlternateKeyDto);
// Get the EMR cluster definition and ensure it exists.
EmrClusterDefinitionEntity emrClusterDefinitionEntity = emrClusterDefinitionDaoHelper.getEmrClusterDefinitionEntity(
new EmrClusterDefinitionKey(emrClusterAlternateKeyDto.getNamespace(), emrClusterAlternateKeyDto.getEmrClusterDefinitionName()));
EmrCluster emrCluster = createEmrClusterFromRequest(null, emrClusterDefinitionEntity.getNamespace().getCode(), emrClusterDefinitionEntity.getName(),
emrClusterAlternateKeyDto.getEmrClusterName(), accountId, null, null, null, null);
String clusterName = emrHelper.buildEmrClusterName(emrClusterDefinitionEntity.getNamespace().getCode(), emrClusterDefinitionEntity.getName(),
emrClusterAlternateKeyDto.getEmrClusterName());
try
{
// Get Cluster status if clusterId is specified
if (StringUtils.isNotBlank(emrClusterId))
{
Cluster cluster = emrDao.getEmrClusterById(emrClusterId.trim(), awsParamsDto);
// Validate that, Cluster exists
Assert.notNull(cluster, "An EMR cluster must exists with the cluster ID \"" + emrClusterId + "\".");
// Validate that, Cluster name match as specified
Assert.isTrue(clusterName.equalsIgnoreCase(cluster.getName()),
"Cluster name of specified cluster id \"" + emrClusterId + "\" must match the name specified.");
emrCluster.setId(cluster.getId());
setEmrClusterStatus(emrCluster, cluster.getStatus());
}
else
{
ClusterSummary clusterSummary = emrDao.getActiveEmrClusterByNameAndAccountId(clusterName, accountId, awsParamsDto);
// Validate that, Cluster exists with the name
Assert.notNull(clusterSummary, "An EMR cluster must exists with the name \"" + clusterName + "\".");
emrCluster.setId(clusterSummary.getId());
setEmrClusterStatus(emrCluster, clusterSummary.getStatus());
}
// Get active step details
if (emrHelper.isActiveEmrState(emrCluster.getStatus()))
{
StepSummary stepSummary = emrDao.getClusterActiveStep(emrCluster.getId(), awsParamsDto);
if (stepSummary != null)
{
EmrStep activeStep;
// If verbose get active step details
if (verbose)
{
activeStep = buildEmrStepFromAwsStep(stepSummary, true);
}
else
{
activeStep = buildEmrStepFromAwsStepSummary(stepSummary);
}
emrCluster.setActiveStep(activeStep);
}
}
// Get requested step details
if (StringUtils.isNotBlank(emrStepId))
{
Step step = emrDao.getClusterStep(emrCluster.getId(), emrStepId.trim(), awsParamsDto);
emrCluster.setStep(buildEmrStepFromAwsStep(step, verbose));
}
// Get instance fleet if true
if (BooleanUtils.isTrue(retrieveInstanceFleets))
{
ListInstanceFleetsResult listInstanceFleetsResult = emrDao.getListInstanceFleetsResult(emrCluster.getId(), awsParamsDto);
emrCluster.setInstanceFleets(emrHelper.buildEmrClusterInstanceFleetFromAwsResult(listInstanceFleetsResult));
}
}
catch (AmazonServiceException ex)
{
awsServiceHelper.handleAmazonException(ex, "An Amazon exception occurred while getting EMR cluster details with name \"" + clusterName + "\".");
}
return emrCluster;
}
/**
* Builds EmrStep object from the EMR step. Fills in details if verbose=true.
*
* @param stepSummary The step summary
* @param verbose The verbose flag
*
* @return EmrStep
*/
private EmrStep buildEmrStepFromAwsStep(StepSummary stepSummary, boolean verbose)
{
EmrStep emrStep = new EmrStep();
emrStep.setId(stepSummary.getId());
emrStep.setStepName(stepSummary.getName());
emrStep.setStatus(stepSummary.getStatus().getState());
if (verbose)
{
emrStep.setJarLocation(stepSummary.getConfig().getJar());
emrStep.setMainClass(stepSummary.getConfig().getMainClass());
emrStep.setScriptArguments(stepSummary.getConfig().getArgs());
emrStep.setContinueOnError(stepSummary.getActionOnFailure());
}
return emrStep;
}
/**
* Builds EmrStep object from the EMR step. Fills in details if verbose=true.
*
* @param step The step
* @param verbose The verbose flag
*
* @return EmrStep
*/
private EmrStep buildEmrStepFromAwsStep(Step step, boolean verbose)
{
EmrStep emrStep = new EmrStep();
emrStep.setId(step.getId());
emrStep.setStepName(step.getName());
emrStep.setStatus(step.getStatus().getState());
if (verbose)
{
emrStep.setJarLocation(step.getConfig().getJar());
emrStep.setMainClass(step.getConfig().getMainClass());
emrStep.setScriptArguments(step.getConfig().getArgs());
emrStep.setContinueOnError(step.getActionOnFailure());
}
return emrStep;
}
/**
* Builds EmrStep object from the EMR StepSummary. Fills in details if verbose=true.
*/
private EmrStep buildEmrStepFromAwsStepSummary(StepSummary stepSummary)
{
EmrStep emrStep = new EmrStep();
emrStep.setId(stepSummary.getId());
emrStep.setStepName(stepSummary.getName());
emrStep.setStatus(stepSummary.getStatus().getState());
return emrStep;
}
/**
* {@inheritDoc}
*
* This implementation starts a new transaction.
*/
@NamespacePermission(fields = "#request?.namespace", permissions = NamespacePermissionEnum.EXECUTE)
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public EmrCluster createCluster(EmrClusterCreateRequest request) throws Exception
{
return createClusterImpl(request);
}
/**
* Creates a new EMR cluster based on the given request if the cluster with the given name does not already exist. If the cluster already exist, returns
* the information about the existing cluster.
The request must contain:
- A namespace and definition name which refer to an existing
* EMR cluster definition.
- A valid cluster name to create.
The request may optionally contain:
- A "dry run" flag, which
* when set to {@code true}, no calls to AWS will occur, but validations and override will. Defaults to {@code false}.
- An override parameter, which
* when set, overrides the given parameters in the cluster definition before creating the cluster. Defaults to no override.
A successful
* response will contain:
- The ID of the cluster that was created, or if the cluster already exists, the ID of the cluster that exists. This
* field will be {@code null} when dry run flag is {@code true}.
- The status of the cluster that was created or already exists. The status will
* normally be "Starting" on successful creations. This field will be {@code null} when dry run flag is {@code true}
- The namespace, definition
* name, and cluster name of the cluster.
- The dry run flag, if given in the request.
- An indicator whether the cluster was created or not.
* If the cluster already exists, the cluster will not be created and this flag will be set to {@code false}.
- The definition which was used to
* create the cluster. If any overrides were given, this definition's values will be the values after the override. This field will be {@code null} if the
* cluster was not created.
Notes:
- At any point of the execution, if there are validation errors, the method will immediately
* throw an exception.
- Even if the validations pass, AWS may still reject the request, which will cause this method to throw an exception.
* - Dry runs do not make any calls to AWS, therefore AWS may still reject the creation request even when a dry run succeeds.
*
* @param request - {@link EmrClusterCreateRequest} The EMR cluster create request
*
* @return {@link EmrCluster} the created EMR cluster object
* @throws Exception when the original EMR cluster definition XML is malformed
*/
protected EmrCluster createClusterImpl(EmrClusterCreateRequest request) throws Exception
{
// Extract EMR cluster alternate key from the create request.
EmrClusterAlternateKeyDto emrClusterAlternateKeyDto = getEmrClusterAlternateKey(request);
// Perform the request validation.
validateEmrClusterKey(emrClusterAlternateKeyDto);
EmrClusterDefinition emrClusterDefinition = emrHelperServiceImpl.emrPreCreateClusterSteps(emrClusterAlternateKeyDto, request);
String accountId = emrClusterDefinition.getAccountId();
EmrClusterCreateDto emrClusterCreateDto =
emrHelperServiceImpl.emrCreateClusterAwsSpecificSteps(request, emrClusterDefinition, emrClusterAlternateKeyDto);
if (emrClusterCreateDto.isEmrClusterCreated())
{
emrHelperServiceImpl.logEmrClusterCreation(emrClusterAlternateKeyDto, emrClusterDefinition, emrClusterCreateDto.getClusterId());
}
if (BooleanUtils.isTrue(emrClusterCreateDto.isEmrClusterAlreadyExists()))
{
// Do not include cluster definition in response
emrClusterDefinition = null;
}
return createEmrClusterFromRequest(emrClusterCreateDto.getClusterId(), emrClusterAlternateKeyDto.getNamespace(),
emrClusterAlternateKeyDto.getEmrClusterDefinitionName(), emrClusterAlternateKeyDto.getEmrClusterName(), accountId,
emrClusterCreateDto.getEmrClusterStatus(), emrClusterCreateDto.isEmrClusterCreated(), request.isDryRun(), emrClusterDefinition);
}
/**
* {@inheritDoc}
*
* This implementation starts a new transaction.
*/
@NamespacePermission(fields = "#emrClusterAlternateKeyDto?.namespace", permissions = NamespacePermissionEnum.EXECUTE)
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EmrCluster terminateCluster(EmrClusterAlternateKeyDto emrClusterAlternateKeyDto, boolean overrideTerminationProtection, String emrClusterId,
String accountId) throws Exception
{
return terminateClusterImpl(emrClusterAlternateKeyDto, overrideTerminationProtection, emrClusterId, accountId);
}
/**
* Terminates the EMR Cluster.
*
* @param emrClusterAlternateKeyDto the EMR cluster alternate key
* @param overrideTerminationProtection parameter for whether to override termination protection
* @param emrClusterId The EMR cluster ID
* @param accountId The account Id
*
* @return the terminated EMR cluster object
*/
protected EmrCluster terminateClusterImpl(EmrClusterAlternateKeyDto emrClusterAlternateKeyDto, boolean overrideTerminationProtection, String emrClusterId,
String accountId)
{
AwsParamsDto awsParamsDto = emrHelper.getAwsParamsDtoByAccountId(accountId);
// Perform the request validation.
validateEmrClusterKey(emrClusterAlternateKeyDto);
// Get the EMR cluster definition and ensure it exists.
EmrClusterDefinitionEntity emrClusterDefinitionEntity = emrClusterDefinitionDaoHelper.getEmrClusterDefinitionEntity(
new EmrClusterDefinitionKey(emrClusterAlternateKeyDto.getNamespace(), emrClusterAlternateKeyDto.getEmrClusterDefinitionName()));
String clusterId = null;
String clusterName = emrHelper.buildEmrClusterName(emrClusterDefinitionEntity.getNamespace().getCode(), emrClusterDefinitionEntity.getName(),
emrClusterAlternateKeyDto.getEmrClusterName());
try
{
clusterId = emrHelper.getActiveEmrClusterId(emrClusterId, clusterName, accountId);
emrDao.terminateEmrCluster(clusterId, overrideTerminationProtection, awsParamsDto);
}
catch (AmazonServiceException ex)
{
awsServiceHelper.handleAmazonException(ex, "An Amazon exception occurred while terminating EMR cluster with name \"" + clusterName + "\".");
}
return createEmrClusterFromRequest(clusterId, emrClusterDefinitionEntity.getNamespace().getCode(), emrClusterDefinitionEntity.getName(),
emrClusterAlternateKeyDto.getEmrClusterName(), accountId, emrDao.getEmrClusterStatusById(clusterId, awsParamsDto), null, null, null);
}
/**
* Creates a EMR cluster alternate key from the relative values in the EMR Cluster Create Request.
*
* @param emrClusterCreateRequest the EMR cluster create request
*
* @return the EMR cluster alternate key
*/
private EmrClusterAlternateKeyDto getEmrClusterAlternateKey(EmrClusterCreateRequest emrClusterCreateRequest)
{
return EmrClusterAlternateKeyDto.builder().withNamespace(emrClusterCreateRequest.getNamespace())
.withEmrClusterDefinitionName(emrClusterCreateRequest.getEmrClusterDefinitionName()).withEmrClusterName(emrClusterCreateRequest.getEmrClusterName())
.build();
}
/**
* Creates a new EMR cluster object from request.
*
* @param clusterId the cluster Id.
* @param namespaceCd the namespace Code
* @param clusterDefinitionName the cluster definition
* @param clusterName the cluster name
* @param accountId the optional AWS account that EMR cluster is running in
* @param clusterStatus the cluster status
* @param emrClusterCreated whether EMR cluster was created.
* @param dryRun The dry run flag.
* @param emrClusterDefinition the EMR cluster definition.
*
* @return the created EMR cluster object
*/
private EmrCluster createEmrClusterFromRequest(String clusterId, String namespaceCd, String clusterDefinitionName, String clusterName, String accountId,
String clusterStatus, Boolean emrClusterCreated, Boolean dryRun, EmrClusterDefinition emrClusterDefinition)
{
// Create the EMR cluster.
EmrCluster emrCluster = new EmrCluster();
emrCluster.setId(clusterId);
emrCluster.setNamespace(namespaceCd);
emrCluster.setEmrClusterDefinitionName(clusterDefinitionName);
emrCluster.setEmrClusterName(clusterName);
emrCluster.setAccountId(accountId);
emrCluster.setStatus(clusterStatus);
emrCluster.setDryRun(dryRun);
emrCluster.setEmrClusterCreated(emrClusterCreated);
emrCluster.setEmrClusterDefinition(emrClusterDefinition);
return emrCluster;
}
/**
* {@inheritDoc}
*
* This implementation starts a new transaction.
*/
@NamespacePermission(fields = "#request?.namespace", permissions = NamespacePermissionEnum.EXECUTE)
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Object addStepToCluster(Object request) throws Exception
{
return addStepToClusterImpl(request);
}
/**
* Adds step to an existing EMR Cluster.
*
* @param request the EMR steps add request
*
* @return the EMR step add object with added steps
* @throws Exception if there were any errors while adding a step to the cluster.
*/
protected Object addStepToClusterImpl(Object request) throws Exception
{
EmrStepHelper stepHelper = emrStepHelperFactory.getStepHelper(request.getClass().getName());
// Perform the request validation.
validateAddStepToClusterRequest(request, stepHelper);
// Perform the step specific validation
stepHelper.validateAddStepRequest(request);
//get accountId and awsParamDto
String accountId = stepHelper.getRequestAccountId(request);
AwsParamsDto awsParamsDto = emrHelper.getAwsParamsDtoByAccountId(accountId);
// Get the EMR cluster definition and ensure it exists.
EmrClusterDefinitionEntity emrClusterDefinitionEntity = emrClusterDefinitionDaoHelper.getEmrClusterDefinitionEntity(
new EmrClusterDefinitionKey(stepHelper.getRequestNamespace(request), stepHelper.getRequestEmrClusterDefinitionName(request)));
// Update the namespace and cluster definition name in request from database.
stepHelper.setRequestNamespace(request, emrClusterDefinitionEntity.getNamespace().getCode());
stepHelper.setRequestEmrClusterDefinitionName(request, emrClusterDefinitionEntity.getName());
String clusterName = emrHelper.buildEmrClusterName(emrClusterDefinitionEntity.getNamespace().getCode(), emrClusterDefinitionEntity.getName(),
stepHelper.getRequestEmrClusterName(request));
Object emrStep = stepHelper.buildResponseFromRequest(request);
try
{
String clusterId =
emrHelper.getActiveEmrClusterId(stepHelper.getRequestEmrClusterId(request), clusterName, stepHelper.getRequestAccountId(request));
stepHelper.setRequestEmrClusterId(request, clusterId);
String stepId = emrDao.addEmrStep(clusterId, stepHelper.getEmrStepConfig(emrStep), awsParamsDto);
stepHelper.setStepId(emrStep, stepId);
}
catch (AmazonServiceException ex)
{
awsServiceHelper.handleAmazonException(ex,
"An Amazon exception occurred while adding EMR step \"" + stepHelper.getRequestStepName(request) + "\" to cluster with name \"" + clusterName +
"\".");
}
return emrStep;
}
/**
* Validates the add steps to EMR cluster create request. This method also trims request parameters.
*
* @param request the request.
*
* @throws IllegalArgumentException if any validation errors were found.
*/
private void validateAddStepToClusterRequest(Object request, EmrStepHelper stepHelper) throws IllegalArgumentException
{
String namespace = stepHelper.getRequestNamespace(request);
String clusterDefinitionName = stepHelper.getRequestEmrClusterDefinitionName(request);
String clusterName = stepHelper.getRequestEmrClusterName(request);
// Validate required elements
Assert.hasText(namespace, "A namespace must be specified.");
Assert.hasText(clusterDefinitionName, "An EMR cluster definition name must be specified.");
Assert.hasText(clusterName, "An EMR cluster name must be specified.");
// Remove leading and trailing spaces.
stepHelper.setRequestNamespace(request, namespace.trim());
stepHelper.setRequestEmrClusterDefinitionName(request, clusterDefinitionName.trim());
stepHelper.setRequestEmrClusterName(request, clusterName.trim());
}
/**
* {@inheritDoc}
*
* This implementation starts a new transaction.
*/
@NamespacePermission(fields = "#request?.namespace", permissions = NamespacePermissionEnum.WRITE)
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public EmrMasterSecurityGroup addSecurityGroupsToClusterMaster(EmrMasterSecurityGroupAddRequest request) throws Exception
{
return addSecurityGroupsToClusterMasterImpl(request);
}
/**
* Adds security groups to the master node of an existing EMR Cluster.
*
* @param request the EMR master security group add request
*
* @return the added EMR master security groups
* @throws Exception if there were any errors adding the security groups to the cluster master.
*/
protected EmrMasterSecurityGroup addSecurityGroupsToClusterMasterImpl(EmrMasterSecurityGroupAddRequest request) throws Exception
{
// Perform the request validation.
validateAddSecurityGroupsToClusterMasterRequest(request);
// Get account and AwsParamDto
String accountId = request.getAccountId();
AwsParamsDto awsParamsDto = emrHelper.getAwsParamsDtoByAccountId(accountId);
// Get the EMR cluster definition and ensure it exists.
EmrClusterDefinitionEntity emrClusterDefinitionEntity = emrClusterDefinitionDaoHelper
.getEmrClusterDefinitionEntity(new EmrClusterDefinitionKey(request.getNamespace(), request.getEmrClusterDefinitionName()));
List groupIds = null;
String clusterName = emrHelper
.buildEmrClusterName(emrClusterDefinitionEntity.getNamespace().getCode(), emrClusterDefinitionEntity.getName(), request.getEmrClusterName());
try
{
groupIds = emrDao.addEmrMasterSecurityGroups(emrHelper.getActiveEmrClusterId(request.getEmrClusterId(), clusterName, request.getAccountId()),
request.getSecurityGroupIds(), awsParamsDto);
}
catch (AmazonServiceException ex)
{
awsServiceHelper.handleAmazonException(ex, "An Amazon exception occurred while adding EMR security groups: " +
herdStringHelper.buildStringWithDefaultDelimiter(request.getSecurityGroupIds()) + " to cluster: " + clusterName);
}
return createEmrClusterMasterGroupFromRequest(emrClusterDefinitionEntity.getNamespace().getCode(), emrClusterDefinitionEntity.getName(),
request.getEmrClusterName(), groupIds);
}
/**
* Validates the add groups to EMR cluster master create request. This method also trims request parameters.
*
* @param request the request.
*
* @throws IllegalArgumentException if any validation errors were found.
*/
private void validateAddSecurityGroupsToClusterMasterRequest(EmrMasterSecurityGroupAddRequest request) throws IllegalArgumentException
{
// Validate required elements
Assert.hasText(request.getNamespace(), "A namespace must be specified.");
Assert.hasText(request.getEmrClusterDefinitionName(), "An EMR cluster definition name must be specified.");
Assert.hasText(request.getEmrClusterName(), "An EMR cluster name must be specified.");
Assert.notEmpty(request.getSecurityGroupIds(), "At least one security group must be specified.");
for (String securityGroup : request.getSecurityGroupIds())
{
Assert.hasText(securityGroup, "A security group value must be specified.");
}
// Remove leading and trailing spaces.
request.setNamespace(request.getNamespace().trim());
request.setEmrClusterDefinitionName(request.getEmrClusterDefinitionName().trim());
request.setEmrClusterName(request.getEmrClusterName().trim());
for (int i = 0; i < request.getSecurityGroupIds().size(); i++)
{
String element = request.getSecurityGroupIds().get(i);
request.getSecurityGroupIds().set(i, element.trim());
}
}
/**
* Creates a new EMR master group object from request.
*
* @param namespaceCd, the namespace Code
* @param clusterDefinitionName, the cluster definition name
* @param clusterName, the cluster name
* @param groupIds, the List of groupId
*
* @return the created EMR master group object
*/
private EmrMasterSecurityGroup createEmrClusterMasterGroupFromRequest(String namespaceCd, String clusterDefinitionName, String clusterName,
List groupIds)
{
// Create the EMR cluster.
EmrMasterSecurityGroup emrMasterSecurityGroup = new EmrMasterSecurityGroup();
emrMasterSecurityGroup.setNamespace(namespaceCd);
emrMasterSecurityGroup.setEmrClusterDefinitionName(clusterDefinitionName);
emrMasterSecurityGroup.setEmrClusterName(clusterName);
emrMasterSecurityGroup.setSecurityGroupIds(groupIds);
return emrMasterSecurityGroup;
}
/**
* Builds the {@link XMLGregorianCalendar} for the given {@link Date}
*
* @param date date
*
* @return XMLGregorianCalendar
*/
private XMLGregorianCalendar toXmlGregorianCalendar(Date date)
{
XMLGregorianCalendar result = null;
if (date != null)
{
result = HerdDateUtils.getXMLGregorianCalendarValue(date);
}
return result;
}
/**
* Validates the EMR cluster create request. This method also trims request parameters.
*
* @param key the ERM cluster alternate key
*
* @throws IllegalArgumentException if any validation errors were found
*/
private void validateEmrClusterKey(EmrClusterAlternateKeyDto key) throws IllegalArgumentException
{
Assert.notNull(key, "An EMR cluster key must be specified.");
key.setNamespace(alternateKeyHelper.validateStringParameter("namespace", key.getNamespace()));
key.setEmrClusterDefinitionName(alternateKeyHelper.validateStringParameter("An", "EMR cluster definition name", key.getEmrClusterDefinitionName()));
key.setEmrClusterName(alternateKeyHelper.validateStringParameter("An", "EMR cluster name", key.getEmrClusterName()));
}
/**
* Updates EMR cluster model object with the specified EMR cluster status information.
*
* @param emrCluster the EMR cluster
* @param clusterStatus the EMR cluster status information
*/
private void setEmrClusterStatus(EmrCluster emrCluster, ClusterStatus clusterStatus)
{
// Log cluster status information.
LOGGER.info("emrClusterId=\"{}\" emrClusterStatus={}", emrCluster.getId(), jsonHelper.objectToJson(clusterStatus));
// Update the EMR cluster with the status information.
emrCluster.setStatus(clusterStatus.getState());
emrCluster
.setStatusChangeReason(new StatusChangeReason(clusterStatus.getStateChangeReason().getCode(), clusterStatus.getStateChangeReason().getMessage()));
emrCluster.setStatusTimeline(new StatusTimeline(toXmlGregorianCalendar(clusterStatus.getTimeline().getCreationDateTime()),
toXmlGregorianCalendar(clusterStatus.getTimeline().getReadyDateTime()), toXmlGregorianCalendar(clusterStatus.getTimeline().getEndDateTime())));
}
}