Search in sources :

Example 26 with Pool

use of bio.terra.buffer.common.Pool in project terra-resource-buffer by DataBiosphere.

the class BufferDao method deactivatePools.

/**
 * Updates list of pools' status to DEACTIVATED.
 */
// TODO: consider delaying expiration so pool can be recovered
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE)
public void deactivatePools(List<PoolId> poolIds) {
    String sql = "UPDATE pool SET status = :status, expiration = :expiration WHERE id = :id ";
    MapSqlParameterSource[] sqlParameterSourceList = poolIds.stream().map(poolId -> new MapSqlParameterSource().addValue("id", poolId.id()).addValue("status", PoolStatus.DEACTIVATED.toString()).addValue("expiration", OffsetDateTime.now(ZoneOffset.UTC))).toArray(MapSqlParameterSource[]::new);
    jdbcTemplate.batchUpdate(sql, sqlParameterSourceList);
}
Also used : DataAccessException(org.springframework.dao.DataAccessException) OBJECT_MAPPER(bio.terra.buffer.app.configuration.BeanNames.OBJECT_MAPPER) LoggerFactory(org.slf4j.LoggerFactory) NamedParameterJdbcTemplate(org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate) Autowired(org.springframework.beans.factory.annotation.Autowired) InternalServerErrorException(bio.terra.common.exception.InternalServerErrorException) HashMap(java.util.HashMap) MapSqlParameterSource(org.springframework.jdbc.core.namedparam.MapSqlParameterSource) ResourceId(bio.terra.buffer.common.ResourceId) PoolId(bio.terra.buffer.common.PoolId) PoolAndResourceStates(bio.terra.buffer.common.PoolAndResourceStates) SQLException(java.sql.SQLException) ResourceState(bio.terra.buffer.common.ResourceState) Propagation(org.springframework.transaction.annotation.Propagation) ResultSet(java.sql.ResultSet) Map(java.util.Map) Qualifier(org.springframework.beans.factory.annotation.Qualifier) ZoneOffset(java.time.ZoneOffset) DataAccessUtils(org.springframework.dao.support.DataAccessUtils) ResourceType(bio.terra.buffer.common.ResourceType) Resource(bio.terra.buffer.common.Resource) Logger(org.slf4j.Logger) CloudResourceUid(bio.terra.buffer.generated.model.CloudResourceUid) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Pool(bio.terra.buffer.common.Pool) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) UUID(java.util.UUID) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) PoolStatus(bio.terra.buffer.common.PoolStatus) CheckReturnValue(javax.annotation.CheckReturnValue) List(java.util.List) Component(org.springframework.stereotype.Component) RequestHandoutId(bio.terra.buffer.common.RequestHandoutId) ResourceConfig(bio.terra.buffer.generated.model.ResourceConfig) OffsetDateTime(java.time.OffsetDateTime) BUFFER_JDBC_TEMPLATE(bio.terra.buffer.app.configuration.BeanNames.BUFFER_JDBC_TEMPLATE) CreateNetworkStep(bio.terra.buffer.service.resource.flight.CreateNetworkStep) RowMapper(org.springframework.jdbc.core.RowMapper) JsonInclude(com.fasterxml.jackson.annotation.JsonInclude) Optional(java.util.Optional) Isolation(org.springframework.transaction.annotation.Isolation) ResultSetExtractor(org.springframework.jdbc.core.ResultSetExtractor) Transactional(org.springframework.transaction.annotation.Transactional) MapSqlParameterSource(org.springframework.jdbc.core.namedparam.MapSqlParameterSource) Transactional(org.springframework.transaction.annotation.Transactional)

Example 27 with Pool

use of bio.terra.buffer.common.Pool in project terra-resource-buffer by DataBiosphere.

the class PoolService method handoutResourceTransactionally.

/**
 * Process handout resource in on transaction (anything failure will cause database rollback).
 */
private Resource handoutResourceTransactionally(PoolId poolId, RequestHandoutId requestHandoutId) {
    Optional<Pool> pool = bufferDao.retrievePool(poolId);
    if (pool.isEmpty() || !pool.get().status().equals(PoolStatus.ACTIVE)) {
        throw new BadRequestException(String.format("Invalid pool id: %s.", poolId));
    }
    try {
        // Retry 20 times of 2 seconds each.
        Optional<Resource> resource = executeAndRetry(() -> bufferDao.updateOneReadyResourceToHandedOut(poolId, requestHandoutId), Duration.ofSeconds(2), 20);
        Resource result = resource.orElseThrow(() -> new NotFoundException(String.format("No resource is ready to use at this moment for pool: %s. Please try later", poolId)));
        logger.info("Handed out resource ID {}, Handout ID {}, Pool ID {}", result.cloudResourceUid(), result.requestHandoutId(), poolId);
        return result;
    } catch (InterruptedException | DataAccessException e) {
        throw new InternalServerErrorException(String.format("Failed to update one resource state from READY to HANDED_OUT for pool %s", poolId));
    }
}
Also used : Resource(bio.terra.buffer.common.Resource) BadRequestException(bio.terra.common.exception.BadRequestException) NotFoundException(bio.terra.buffer.common.exception.NotFoundException) InternalServerErrorException(bio.terra.common.exception.InternalServerErrorException) Pool(bio.terra.buffer.common.Pool) DataAccessException(org.springframework.dao.DataAccessException)

Example 28 with Pool

use of bio.terra.buffer.common.Pool in project terra-resource-buffer by DataBiosphere.

the class PoolService method updateFromConfig.

/**
 * Given parsed pool configurations, create new pools, deactivate removed pools, or update pool
 * size, as required.
 *
 * @param parsedPoolConfigs - previously parsed pool/resource configurations
 */
@VisibleForTesting
public void updateFromConfig(List<PoolWithResourceConfig> parsedPoolConfigs) {
    transactionTemplate.execute(unused -> {
        final Map<PoolId, Pool> allDbPoolsMap = Maps.uniqueIndex(bufferDao.retrievePools(), Pool::id);
        final Map<PoolId, PoolWithResourceConfig> parsedPoolConfigMap = Maps.uniqueIndex(parsedPoolConfigs, config -> PoolId.create(config.poolConfig().getPoolId()));
        final Set<PoolId> allPoolIds = Sets.union(allDbPoolsMap.keySet(), parsedPoolConfigMap.keySet());
        final List<PoolWithResourceConfig> poolsToCreate = new ArrayList<>();
        final List<Pool> poolsToDeactivate = new ArrayList<>();
        final List<PoolWithResourceConfig> poolsToReactivate = new ArrayList<>();
        final Map<PoolId, Integer> poolIdToNewSize = new HashMap<>();
        // on the change.
        for (PoolId id : allPoolIds) {
            if (parsedPoolConfigMap.containsKey(id) && !allDbPoolsMap.containsKey(id)) {
                // Exists in config but not in DB.
                poolsToCreate.add(parsedPoolConfigMap.get(id));
            } else if (!parsedPoolConfigMap.containsKey(id) && allDbPoolsMap.containsKey(id)) {
                // Exists in DB but not in Config.
                poolsToDeactivate.add(allDbPoolsMap.get(id));
            } else {
                // Exists in DB and Config.
                final Pool dbPool = allDbPoolsMap.get(id);
                final PoolWithResourceConfig configPool = parsedPoolConfigMap.get(id);
                if (dbPool.status().equals(PoolStatus.DEACTIVATED)) {
                    PoolWithResourceConfig poolWithConfig = parsedPoolConfigMap.get(id);
                    // Re-activate a deactivated pool
                    poolsToReactivate.add(poolWithConfig);
                }
                if (!dbPool.resourceConfig().equals(configPool.resourceConfig())) {
                    // ResourceConfig name when loading from file.
                    throw new BadPoolConfigException(String.format("Updating ResourceConfig on existing pool (id= %s) " + "is not allowed for any attributes except size. " + "Please create a new pool config instead.", id));
                } else if (dbPool.size() != (configPool.poolConfig().getSize())) {
                    // Exists in both places but need to update size.
                    poolIdToNewSize.put(dbPool.id(), configPool.poolConfig().getSize());
                }
            }
        }
        createPools(poolsToCreate);
        deactivatePools(poolsToDeactivate);
        reactivatePools(poolsToReactivate);
        updatePoolSizes(poolIdToNewSize);
        return true;
    });
}
Also used : PoolId(bio.terra.buffer.common.PoolId) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Pool(bio.terra.buffer.common.Pool) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 29 with Pool

use of bio.terra.buffer.common.Pool in project terra-resource-buffer by DataBiosphere.

the class PoolService method getPoolInfo.

/**
 * Gets pool information by given {@link PoolId}.
 */
public PoolInfo getPoolInfo(PoolId poolId) {
    Optional<PoolAndResourceStates> poolAndResourceStates = bufferDao.retrievePoolAndResourceStatesById(poolId);
    if (poolAndResourceStates.isEmpty()) {
        throw new NotFoundException(String.format("Pool %s not found", poolId));
    }
    Pool pool = poolAndResourceStates.get().pool();
    Multiset<ResourceState> resourceStates = poolAndResourceStates.get().resourceStates();
    return new PoolInfo().poolConfig(new PoolConfig().poolId(poolId.toString()).size(pool.size()).resourceConfigName(pool.resourceConfig().getConfigName())).status(bio.terra.buffer.generated.model.PoolStatus.valueOf(pool.status().toString())).putResourceStateCountItem(ResourceState.CREATING.name(), resourceStates.count(ResourceState.CREATING)).putResourceStateCountItem(ResourceState.READY.name(), resourceStates.count(ResourceState.READY)).putResourceStateCountItem(ResourceState.DELETED.name(), resourceStates.count(ResourceState.DELETED)).putResourceStateCountItem(ResourceState.HANDED_OUT.name(), resourceStates.count(ResourceState.HANDED_OUT));
}
Also used : PoolAndResourceStates(bio.terra.buffer.common.PoolAndResourceStates) NotFoundException(bio.terra.buffer.common.exception.NotFoundException) PoolConfig(bio.terra.buffer.generated.model.PoolConfig) PoolConfigLoader.loadPoolConfig(bio.terra.buffer.service.pool.PoolConfigLoader.loadPoolConfig) Pool(bio.terra.buffer.common.Pool) ResourceState(bio.terra.buffer.common.ResourceState) PoolInfo(bio.terra.buffer.generated.model.PoolInfo)

Example 30 with Pool

use of bio.terra.buffer.common.Pool in project terra-resource-buffer by DataBiosphere.

the class CleanupSchedulerTest method testScheduleCleanup.

@Test
public void testScheduleCleanup() throws Exception {
    Pool pool = Pool.builder().creation(CREATION).id(PoolId.create("poolId")).resourceType(ResourceType.GOOGLE_PROJECT).size(1).resourceConfig(new ResourceConfig()).status(PoolStatus.ACTIVE).build();
    CloudResourceUid cloudResourceUid = new CloudResourceUid().googleProjectUid(new GoogleProjectUid().projectId("p1"));
    Resource resource = Resource.builder().id(ResourceId.create(UUID.randomUUID())).poolId(pool.id()).creation(Instant.now()).state(ResourceState.CREATING).build();
    bufferDao.createPools(ImmutableList.of(pool));
    bufferDao.createResource(resource);
    bufferDao.updateResourceAsReady(resource.id(), cloudResourceUid);
    bufferDao.updateOneReadyResourceToHandedOut(pool.id(), RequestHandoutId.create("1111"));
    assertEquals(1, bufferDao.retrieveResourceToCleanup(10).size());
    cleanupScheduler.initialize();
    Thread.sleep(1000);
    verify(mockPublisher).publish(messageArgumentCaptor.capture());
    assertThat(messageArgumentCaptor.getAllValues().stream().map(m -> m.getData().toStringUtf8()).collect(Collectors.toList()), Matchers.containsInAnyOrder(objectMapper.writeValueAsString(new CreateResourceRequestBody().creation(CREATION.atOffset(ZoneOffset.UTC)).expiration(CREATION.plus(crlConfiguration.getTestResourceTimeToLive()).atOffset(ZoneOffset.UTC)).putLabelsItem("client", CLIENT_NAME).resourceUid(new bio.terra.janitor.model.CloudResourceUid().googleProjectUid(new bio.terra.janitor.model.GoogleProjectUid().projectId("p1"))))));
    assertTrue(bufferDao.retrieveResourceToCleanup(10).isEmpty());
}
Also used : CloudResourceUid(bio.terra.buffer.generated.model.CloudResourceUid) CreateResourceRequestBody(bio.terra.janitor.model.CreateResourceRequestBody) Resource(bio.terra.buffer.common.Resource) Pool(bio.terra.buffer.common.Pool) ResourceConfig(bio.terra.buffer.generated.model.ResourceConfig) GoogleProjectUid(bio.terra.buffer.generated.model.GoogleProjectUid) BaseUnitTest(bio.terra.buffer.common.BaseUnitTest) Test(org.junit.jupiter.api.Test)

Aggregations

Pool (bio.terra.buffer.common.Pool)49 Test (org.junit.jupiter.api.Test)43 BaseUnitTest (bio.terra.buffer.common.BaseUnitTest)25 Resource (bio.terra.buffer.common.Resource)21 BaseIntegrationTest (bio.terra.buffer.common.BaseIntegrationTest)18 IntegrationUtils.preparePool (bio.terra.buffer.integration.IntegrationUtils.preparePool)18 FlightManager (bio.terra.buffer.service.resource.FlightManager)18 ResourceId (bio.terra.buffer.common.ResourceId)17 PoolId (bio.terra.buffer.common.PoolId)13 Project (com.google.api.services.cloudresourcemanager.v3.model.Project)13 PoolConfig (bio.terra.buffer.generated.model.PoolConfig)7 StubSubmissionFlightFactory (bio.terra.buffer.integration.IntegrationUtils.StubSubmissionFlightFactory)7 ResourceConfig (bio.terra.buffer.generated.model.ResourceConfig)4 PoolAndResourceStates (bio.terra.buffer.common.PoolAndResourceStates)3 RequestHandoutId (bio.terra.buffer.common.RequestHandoutId)3 ResourceState (bio.terra.buffer.common.ResourceState)3 ResourceType (bio.terra.buffer.common.ResourceType)3 bio.terra.buffer.generated.model (bio.terra.buffer.generated.model)3 CloudResourceUid (bio.terra.buffer.generated.model.CloudResourceUid)3 PrimaryConfiguration (bio.terra.buffer.app.configuration.PrimaryConfiguration)2