access.deploy.Leaser.java Source code

Java tutorial

Introduction

Here is the source code for access.deploy.Leaser.java

Source

/**
 * Copyright 2016, RadiantBlue Technologies, Inc.
 * 
 * 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 access.deploy;

import org.joda.time.DateTime;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import access.database.DatabaseAccessor;
import model.data.deployment.Deployment;
import model.data.deployment.Lease;
import model.logger.AuditElement;
import model.logger.Severity;
import util.PiazzaLogger;
import util.UUIDFactory;

/**
 * Handles the leasing of deployments of Resources. When a Resource is deployed, it is assigned a lease for a certain
 * period of time. Leasing allows Piazza resources to be managed over time, so that deployments do not live forever and
 * potentially clog up resources. Leases are created when Access Jobs are processed. If a Deployment runs out of a
 * lease, it is vulnerable to being cleaned up by resource reaping.
 * 
 * @author Patrick.Doody
 * 
 */
@Component
public class Leaser {
    @Autowired
    private Deployer deployer;
    @Autowired
    private PiazzaLogger pzLogger;
    @Autowired
    private UUIDFactory uuidFactory;
    @Autowired
    private DatabaseAccessor accessor;

    private static final Integer DEFAULT_LEASE_PERIOD_DAYS = 21;

    private static final Logger LOGGER = LoggerFactory.getLogger(Leaser.class);
    private static final String ACCESS = "access";

    /**
     * Renews the existing Deployment. This Deployment must exist in the Deployments collection.
     * 
     * @param deployment
     *            The deployment to renew.
     * @param durationDays
     *            The number of days to renew the lease by.
     * @return The Lease for this Deployment
     */
    public Lease renewDeploymentLease(Deployment deployment, Integer durationDays) {
        Lease lease = accessor.getDeploymentLease(deployment);
        // If the lease has been reaped by the database, then create a new
        // Lease.
        if (lease == null) {
            lease = createDeploymentLease(deployment, durationDays);
        } else {
            DateTime expirationDate = new DateTime(lease.getExpiresOn());
            if (expirationDate.isBeforeNow()) {
                // If the Lease has expired, then the Lease will be extended for
                // the default Lease period.
                Integer updatedDurationDays = ((durationDays != null) && (durationDays.intValue() > 0))
                        ? durationDays
                        : DEFAULT_LEASE_PERIOD_DAYS;
                accessor.updateLeaseExpirationDate(lease.getLeaseId(),
                        DateTime.now().plusDays(updatedDurationDays.intValue()).toString());
                pzLogger.log(
                        String.format("Updating Deployment Lease for Deployment %s on host %s for %s",
                                deployment.getDeploymentId(), deployment.getHost(), deployment.getDataId()),
                        Severity.INFORMATIONAL,
                        new AuditElement(ACCESS, "renewDeploymentLease", deployment.getDeploymentId()));
            } else {
                // If the Lease has not expired, then the Lease will not be
                // extended. It will simply be reused.
            }
        }

        return lease;
    }

    /**
     * Creates a new lease for the Deployment.
     * 
     * @param deployment
     *            Deployment to create a lease for
     * @param durationDays
     *            the Number of days to create the deployment for
     */
    public Lease createDeploymentLease(Deployment deployment, Integer durationDays) {
        // Create the Lease
        String leaseId = uuidFactory.getUUID();
        Integer updatedDurationDays = ((durationDays != null) && (durationDays.intValue() > 0)) ? durationDays
                : DEFAULT_LEASE_PERIOD_DAYS;
        Lease lease = new Lease(leaseId, deployment.getDeploymentId(),
                DateTime.now().plusDays(updatedDurationDays.intValue()));

        // Commit the Lease to the Database
        accessor.insertLease(lease);

        // Return reference
        pzLogger.log(
                String.format("Creating Deployment Lease for Deployment %s on host %s for %s",
                        deployment.getDeploymentId(), deployment.getHost(), deployment.getDataId()),
                Severity.INFORMATIONAL, new AuditElement(ACCESS, "createDeploymentLease", leaseId));
        return lease;
    }

    /**
     * <p>
     * This method is scheduled to run periodically and look for leases that are expired. If a lease is found to be
     * expired, and GeoServer resources are limited, then the lease will be terminated.
     * </p>
     * 
     * <p>
     * Leases might not be terminated if they are expired, if GeoServer has more than adequate resources available. This
     * is configurable, but ultimately the goal is to create a friendly user experience while not bogging down GeoServer
     * with lots of old, unused deployments.
     * </p>
     * 
     * <p>
     * This will currently run every day at 3:00am.
     * </p>
     */
    @Scheduled(cron = "0 0 3 * * ?")
    public void reapExpiredLeases() {
        // Log the initiation of reaping.
        pzLogger.log("Running scheduled daily reaping of expired Deployment Leases.", Severity.INFORMATIONAL);

        // Determine if GeoServer is reaching capacity of its resources.
        // TODO: Not sure if this is needed just yet.
        pzLogger.log("GeoServer not at capacity. No reaping of resources required.", Severity.INFORMATIONAL);

        Iterable<Lease> leases = accessor.getExpiredLeases(DateTime.now());
        for (Lease expiredLease : leases) {
            // There are leases with expired deployments. Remove them.
            try {
                deployer.undeploy(expiredLease.getDeploymentId());
                // Log the removal
                pzLogger.log(String.format(
                        "Expired Lease with Id %s with expiration date %s for Deployment %s has been removed.",
                        expiredLease.getLeaseId(), expiredLease.getExpiresOn(), expiredLease.getDeploymentId()),
                        Severity.INFORMATIONAL,
                        new AuditElement(ACCESS, "reapExpiredLease", expiredLease.getDeploymentId()));
            } catch (Exception exception) {
                String error = String.format(
                        "Error reaping Expired Lease with Id %s: %s. This expired lease may still persist.",
                        expiredLease.getLeaseId(), exception.getMessage());
                LOGGER.error(error, exception);
                pzLogger.log(error, Severity.ERROR);
            }
        }
    }
}