class ClusterCreationSetupService {

    public Cluster prepare(
            ClusterV4Request request,
            Stack stack,
            Blueprint blueprint,
            User user,
            String parentEnvironmentCloudPlatform) throws IOException,
            CloudbreakImageCatalogException, TransactionExecutionException {
        String stackName = stack.getName();
        Cluster clusterStub = stack.getCluster();
        stack.setCluster(null);

        if (request.getCloudStorage() != null) {
            FileSystem fileSystem = cloudStorageConverter.requestToFileSystem(request.getCloudStorage());
            measure(() -> fileSystemConfigService.createWithMdcContextRestore(fileSystem, stack.getWorkspace(), stack.getCreator()),
                    LOGGER, "File system saving took {} ms for stack {}", stackName);
        }

        clusterStub.setStack(stack);
        clusterStub.setWorkspace(stack.getWorkspace());

        Cluster cluster =  measure(() ->
                clusterDecorator.decorate(clusterStub, request, blueprint, user, stack.getWorkspace(), stack, parentEnvironmentCloudPlatform),
                LOGGER,
                "Cluster decorator {} ms for stack {}", stackName);

        List<ClusterComponent> components = multiCheckedMeasure(
                (MultiCheckedSupplier<List<ClusterComponent>, IOException, CloudbreakImageCatalogException>) () -> {
                    if (blueprint != null) {
                        Set<Component> allComponent = componentConfigProviderService.getAllComponentsByStackIdAndType(stack.getId(),
                                Sets.newHashSet(ComponentType.CM_REPO_DETAILS, ComponentType.CDH_PRODUCT_DETAILS, ComponentType.IMAGE));

                        Optional<Component> stackCmRepoConfig = allComponent.stream()
                                .filter(c -> c.getComponentType().equals(ComponentType.CM_REPO_DETAILS))
                                .findAny();

                        List<Component> stackCdhRepoConfig = allComponent.stream()
                                .filter(c -> c.getComponentType().equals(ComponentType.CDH_PRODUCT_DETAILS))
                                .collect(Collectors.toList());

                        Optional<Component> stackImageComponent = allComponent.stream().filter(c -> c.getComponentType().equals(ComponentType.IMAGE)
                                && c.getName().equalsIgnoreCase(ComponentType.IMAGE.name())).findAny();
                        return clouderaManagerClusterCreationSetupService.prepareClouderaManagerCluster(
                                request, cluster, stackCmRepoConfig, stackCdhRepoConfig, stackImageComponent);
                    }
                    return Collections.emptyList();
                }, LOGGER, "Cluster components saved in {} ms for stack {}", stackName);

        return clusterOperationService.create(stack, cluster, components, user);
    }

}