package com.sequenceiq.cloudbreak.service.image;
import static com.sequenceiq.cloudbreak.cloud.model.Platform.platform;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
import javax.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.io.BaseEncoding;
import com.sequenceiq.cloudbreak.api.model.InstanceGroupType;
import com.sequenceiq.cloudbreak.client.PkiUtil;
import com.sequenceiq.cloudbreak.cloud.PlatformParameters;
import com.sequenceiq.cloudbreak.cloud.model.AmbariRepo;
import com.sequenceiq.cloudbreak.cloud.model.HDPInfo;
import com.sequenceiq.cloudbreak.cloud.model.Image;
import com.sequenceiq.cloudbreak.cloud.model.Platform;
import com.sequenceiq.cloudbreak.common.type.ComponentType;
import com.sequenceiq.cloudbreak.core.CloudbreakImageNotFoundException;
import com.sequenceiq.cloudbreak.domain.Component;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.domain.json.Json;
import com.sequenceiq.cloudbreak.service.CloudbreakServiceException;
import com.sequenceiq.cloudbreak.service.ComponentConfigProvider;
import com.sequenceiq.cloudbreak.service.TlsSecurityService;
@Service
@Transactional
public class ImageService {
private static final Logger LOGGER = LoggerFactory.getLogger(ImageService.class);
@Inject
private ImageNameUtil imageNameUtil;
@Inject
private HdpInfoSearchService hdpInfoSearchService;
@Inject
private UserDataBuilder userDataBuilder;
@Inject
private ComponentConfigProvider componentConfigProvider;
@Inject
private TlsSecurityService tlsSecurityService;
public Image getImage(Long stackId) throws CloudbreakImageNotFoundException {
return componentConfigProvider.getImage(stackId);
}
@Transactional(Transactional.TxType.NEVER)
public void create(Stack stack, PlatformParameters params, String ambariVersion, String hdpVersion, String imageCatalog, Optional<String> customImage)
throws CloudbreakImageNotFoundException {
try {
Platform platform = platform(stack.cloudPlatform());
String platformString = platform(stack.cloudPlatform()).value().toLowerCase();
String imageName = imageNameUtil.determineImageName(platformString, stack.getRegion(), ambariVersion, hdpVersion, customImage);
String cbPrivKey = new String(BaseEncoding.base64().decode(stack.getSecurityConfig().getCloudbreakSshPrivateKey()));
String cbSshKey = new String(BaseEncoding.base64().decode(stack.getSecurityConfig().getCloudbreakSshPublicKey()));
byte[] cbSshKeyDer = PkiUtil.getPublicKeyDer(cbPrivKey);
String sshUser = stack.getCredential().getLoginUserName();
String publicSssKey = stack.getCredential().getPublicKey();
Map<InstanceGroupType, String> userData = userDataBuilder.buildUserData(platform, publicSssKey, cbSshKeyDer, cbSshKey, sshUser, params,
stack.getRelocateDocker() == null ? false : stack.getRelocateDocker(), stack.getSecurityConfig().getSaltBootPassword());
HDPInfo hdpInfo = hdpInfoSearchService.searchHDPInfo(platformString, ambariVersion, hdpVersion, imageCatalog);
if (hdpInfo != null) {
String specificImage = imageNameUtil.determineImageName(hdpInfo, platformString, stack.getRegion(), customImage);
if (specificImage == null) {
LOGGER.warn("Cannot find image in the catalog, fallback to default image, ambari: {}, hdp: {}", ambariVersion, hdpVersion);
hdpInfo = null;
} else {
LOGGER.info("Determined image from catalog: {}", specificImage);
imageName = specificImage;
}
}
List<Component> components = new ArrayList<>();
Image image;
if (hdpInfo == null) {
image = new Image(imageName, userData);
} else {
AmbariRepo ambariRepo = new AmbariRepo();
ambariRepo.setPredefined(Boolean.TRUE);
Component ambariRepoComponent = new Component(ComponentType.AMBARI_REPO_DETAILS, ComponentType.AMBARI_REPO_DETAILS.name(),
new Json(ambariRepo), stack);
components.add(ambariRepoComponent);
Component hdpRepoComponent = new Component(ComponentType.HDP_REPO_DETAILS, ComponentType.HDP_REPO_DETAILS.name(),
new Json(hdpInfo.getRepo()), stack);
components.add(hdpRepoComponent);
image = new Image(imageName, userData);
}
Component component = new Component(ComponentType.IMAGE, ComponentType.IMAGE.name(), new Json(image), stack);
components.add(component);
componentConfigProvider.store(components);
} catch (JsonProcessingException e) {
throw new CloudbreakServiceException("Failed to create json", e);
}
}
}