Skip to content

Commit

Permalink
Merge pull request #515 from iExecBlockchainComputing/feature/gramine
Browse files Browse the repository at this point in the history
Feature/gramine
  • Loading branch information
jeremyjams authored Sep 20, 2022
2 parents e94d444 + a99765b commit ff9ce31
Show file tree
Hide file tree
Showing 24 changed files with 375 additions and 114 deletions.
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
version=7.1.0
iexecCommonVersion=6.0.0
iexecCommonVersion=6.0.1-NEXT-SNAPSHOT
iexecBlockchainAdapterVersion=7.1.1
iexecResultVersion=7.1.0
iexecSmsVersion=7.1.0
iexecSmsVersion=7.1.0-NEXT-SNAPSHOT

nexusUser
nexusPassword
27 changes: 27 additions & 0 deletions src/main/java/com/iexec/core/configuration/PurgeConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.iexec.core.configuration;

import com.iexec.common.lifecycle.purge.PurgeService;
import com.iexec.common.lifecycle.purge.Purgeable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
@Slf4j
public class PurgeConfiguration {
/**
* Creates a {@link PurgeService} bean, with a list of all {@link Purgeable} beans as a parameter.
* <p>
* If no {@link Purgeable} bean is known, then an empty list is passed as a parameter.
* This is a special case of Spring IoC, please see
* <a href="https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-autowired-annotation">Spring documentation</a>.
* @param purgeableServices List of services that can be purged on a task completion
* @return An instance of {@link PurgeService} containing a list of all {@link Purgeable} beans.
*/
@Bean
PurgeService purgeService(List<Purgeable> purgeableServices) {
return new PurgeService(purgeableServices);
}
}
52 changes: 0 additions & 52 deletions src/main/java/com/iexec/core/configuration/SmsConfiguration.java

This file was deleted.

25 changes: 17 additions & 8 deletions src/main/java/com/iexec/core/replicate/ReplicateSupplyService.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package com.iexec.core.replicate;

import com.iexec.common.chain.WorkerpoolAuthorization;
import com.iexec.common.lifecycle.purge.ExpiringTaskMapFactory;
import com.iexec.common.lifecycle.purge.Purgeable;
import com.iexec.common.notification.TaskNotification;
import com.iexec.common.notification.TaskNotificationExtra;
import com.iexec.common.notification.TaskNotificationType;
Expand All @@ -33,33 +35,27 @@
import com.iexec.core.task.update.TaskUpdateRequestManager;
import com.iexec.core.worker.Worker;
import com.iexec.core.worker.WorkerService;
import net.jodah.expiringmap.ExpiringMap;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static com.iexec.common.replicate.ReplicateStatus.*;
import static com.iexec.core.task.Task.LONGEST_TASK_TIMEOUT;


@Service
public class ReplicateSupplyService {
public class ReplicateSupplyService implements Purgeable {

private final ReplicatesService replicatesService;
private final SignatureService signatureService;
private final TaskService taskService;
private final TaskUpdateRequestManager taskUpdateRequestManager;
private final WorkerService workerService;
private final Web3jService web3jService;
final Map<String, Lock> taskAccessForNewReplicateLocks =
ExpiringMap.builder()
.expiration(LONGEST_TASK_TIMEOUT.getSeconds(), TimeUnit.SECONDS)
.build();
final Map<String, Lock> taskAccessForNewReplicateLocks = ExpiringTaskMapFactory.getExpiringTaskMap();

public ReplicateSupplyService(ReplicatesService replicatesService,
SignatureService signatureService,
Expand Down Expand Up @@ -532,4 +528,17 @@ private TaskAbortCause getTaskAbortCause(Task task) {
return TaskAbortCause.UNKNOWN;
}
}

// region purge locks
@Override
public boolean purgeTask(String chainTaskId) {
taskAccessForNewReplicateLocks.remove(chainTaskId);
return !taskAccessForNewReplicateLocks.containsKey(chainTaskId);
}

@Override
public void purgeAllTasksData() {
taskAccessForNewReplicateLocks.clear();
}
// endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.iexec.core.sms;

import com.iexec.sms.api.SmsClientProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SmsClientProviderConfiguration {

@Bean
SmsClientProvider smsClientProvider() {
return new SmsClientProvider();
}
}
74 changes: 70 additions & 4 deletions src/main/java/com/iexec/core/sms/SmsService.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@

package com.iexec.core.sms;

import com.iexec.common.chain.ChainDeal;
import com.iexec.common.chain.IexecHubAbstractService;
import com.iexec.common.task.TaskDescription;
import com.iexec.common.tee.TeeEnclaveProvider;
import com.iexec.common.tee.TeeUtils;
import com.iexec.common.utils.BytesUtils;
import com.iexec.sms.api.SmsClient;
import com.iexec.sms.api.SmsClientCreationException;
import com.iexec.sms.api.SmsClientProvider;
import feign.FeignException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Recover;
Expand All @@ -30,10 +37,63 @@
@Slf4j
@Service
public class SmsService {
private final SmsClient smsClient;
private final SmsClientProvider smsClientProvider;
private final IexecHubAbstractService iexecHubService;

public SmsService(SmsClient smsClient) {
this.smsClient = smsClient;
public SmsService(SmsClientProvider smsClientProvider, IexecHubAbstractService iexecHubService) {
this.smsClientProvider = smsClientProvider;
this.iexecHubService = iexecHubService;
}

/**
* Checks the following conditions:
* <ul>
* <li>Given deal exists on-chain;</li>
* <li>The {@link SmsClient} can be created, based on the on-chain deal definition;</li>
* <li>The targeted SMS is configured to run with the task's TEE enclave provider.</li>
* </ul>
* <p>
* If any of these conditions is wrong, then the {@link SmsClient} is considered to be not-ready.
*
* @param chainDealId ID of the on-chain deal related to the task to execute.
* @param chainTaskId ID of the on-chain task.
* @return {@literal true} if previous conditions are met, {@literal false} otherwise.
*/
public boolean isSmsClientReady(String chainDealId, String chainTaskId) {
try {
final Optional<ChainDeal> chainDeal = iexecHubService.getChainDeal(chainDealId);
if (chainDeal.isEmpty()) {
log.error("No chain deal for given ID [chainDealId: {}]", chainDealId);
return false;
}
final SmsClient smsClient = smsClientProvider.getOrCreateSmsClientForUninitializedTask(chainDeal.get(), chainTaskId);
final TeeEnclaveProvider teeEnclaveProviderForDeal = TeeUtils.getTeeEnclaveProvider(chainDeal.get().getTag());
return checkSmsTeeEnclaveProvider(smsClient, teeEnclaveProviderForDeal, chainTaskId);
} catch (SmsClientCreationException e) {
log.error("SmsClient is not ready [chainTaskId: {}]", chainTaskId, e);
return false;
}
}

private boolean checkSmsTeeEnclaveProvider(SmsClient smsClient,
TeeEnclaveProvider teeEnclaveProviderForDeal,
String chainTaskId) {
final TeeEnclaveProvider smsTeeEnclaveProvider;
try {
smsTeeEnclaveProvider = smsClient.getTeeEnclaveProvider();
} catch (FeignException e) {
log.error("Can't retrieve SMS TEE enclave provider [chainTaskId:{}]",
chainTaskId, e);
return false;
}

if (smsTeeEnclaveProvider != teeEnclaveProviderForDeal) {
log.error("SMS is configured for another TEE enclave provider " +
"[chainTaskId:{}, teeEnclaveProviderForDeal:{}, smsTeeEnclaveProvider:{}]",
chainTaskId, teeEnclaveProviderForDeal, smsTeeEnclaveProvider);
return false;
}
return true;
}

public Optional<String> getEnclaveChallenge(String chainTaskId, boolean isTeeEnabled) {
Expand All @@ -44,8 +104,14 @@ public Optional<String> getEnclaveChallenge(String chainTaskId, boolean isTeeEna

@Retryable(value = FeignException.class)
Optional<String> generateEnclaveChallenge(String chainTaskId) {
final TaskDescription taskDescription = iexecHubService.getTaskDescription(chainTaskId);

// SMS client should already have been created once before.
// If it couldn't be created, then the task would have been aborted.
// So the following won't throw an exception.
final SmsClient smsClient = smsClientProvider.getOrCreateSmsClientForTask(taskDescription);

String teeChallengePublicKey = smsClient.generateTeeChallenge(chainTaskId);
final String teeChallengePublicKey = smsClient.generateTeeChallenge(chainTaskId);

if (teeChallengePublicKey == null || teeChallengePublicKey.isEmpty()) {
log.error("An error occurred while getting teeChallengePublicKey [chainTaskId:{}]", chainTaskId);
Expand Down
4 changes: 0 additions & 4 deletions src/main/java/com/iexec/core/task/Task.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ public class Task {

public static final String CURRENT_STATUS_FIELD_NAME = "currentStatus";
public static final String CONTRIBUTION_DEADLINE_FIELD_NAME = "contributionDeadline";
/**
* An XL task timeout happens after 100 hours.
*/
public static final Duration LONGEST_TASK_TIMEOUT = Duration.ofHours(100);

@Id
private String id;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/iexec/core/task/TaskRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ interface TaskRepository extends MongoRepository<Task, String> {
* </ul>
*
* @param statuses The task status should be one of this list.
* @param excludedTag The task tag should not be this tag
* @param excludedTags The task tag should not be one this tag list
* - use {@literal null} if no tag should be excluded.
* @param excludedChainTaskIds The chain task ID should not be one of this list.
* @param sort How to prioritize tasks.
* @return The first task matching with the criteria, according to the {@code sort} parameter.
*/
Optional<Task> findFirstByCurrentStatusInAndTagNotAndChainTaskIdNotIn(List<TaskStatus> statuses, String excludedTag, List<String> excludedChainTaskIds, Sort sort);
Optional<Task> findFirstByCurrentStatusInAndTagNotInAndChainTaskIdNotIn(List<TaskStatus> statuses, List<String> excludedTags, List<String> excludedChainTaskIds, Sort sort);

@Query("{ 'currentStatus': {$nin: ?0} }")
List<Task> findByCurrentStatusNotIn(List<TaskStatus> statuses);
Expand Down
19 changes: 8 additions & 11 deletions src/main/java/com/iexec/core/task/TaskService.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;

import static com.iexec.core.task.TaskStatus.*;
Expand Down Expand Up @@ -149,19 +146,19 @@ public List<Task> findByCurrentStatus(List<TaskStatus> statusList) {
public Optional<Task> getPrioritizedInitializedOrRunningTask(
boolean shouldExcludeTeeTasks,
List<String> excludedChainTaskIds) {
final String excludedTag = shouldExcludeTeeTasks
? TeeUtils.TEE_TAG
final List<String> excludedTags = shouldExcludeTeeTasks
? List.of(TeeUtils.TEE_SCONE_ONLY_TAG, TeeUtils.TEE_GRAMINE_ONLY_TAG)
: null;
return findPrioritizedTask(
Arrays.asList(INITIALIZED, RUNNING),
excludedTag,
excludedTags,
excludedChainTaskIds,
Sort.by(Sort.Order.desc(Task.CURRENT_STATUS_FIELD_NAME),
Sort.Order.asc(Task.CONTRIBUTION_DEADLINE_FIELD_NAME)));
}

/**
* Shortcut for {@link TaskRepository#findFirstByCurrentStatusInAndTagNotAndChainTaskIdNotIn}.
* Shortcut for {@link TaskRepository#findFirstByCurrentStatusInAndTagNotInAndChainTaskIdNotIn}.
* Retrieves the prioritized task matching with given criteria:
* <ul>
* <li>Task is in one of given {@code statuses};</li>
Expand All @@ -180,12 +177,12 @@ public Optional<Task> getPrioritizedInitializedOrRunningTask(
* @return The first task matching with the criteria, according to the {@code sort} parameter.
*/
private Optional<Task> findPrioritizedTask(List<TaskStatus> statuses,
String excludedTag,
List<String> excludedTags,
List<String> excludedChainTaskIds,
Sort sort) {
return taskRepository.findFirstByCurrentStatusInAndTagNotAndChainTaskIdNotIn(
return taskRepository.findFirstByCurrentStatusInAndTagNotInAndChainTaskIdNotIn(
statuses,
excludedTag,
excludedTags,
excludedChainTaskIds,
sort
);
Expand Down
Loading

0 comments on commit ff9ce31

Please sign in to comment.