/*
* The MIT License
*
* Copyright 2011 Sony Ericsson Mobile Communications. All rights reserved.
* Copyright 2012 Sony Mobile Communications AB. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.sonyericsson.jenkins.plugins.externalresource.dispatcher.utils.resourcemanagers;
import com.sonyericsson.hudson.plugins.metadata.model.values.AbstractMetadataValue;
import com.sonyericsson.jenkins.plugins.externalresource.dispatcher.data.ExternalResource;
import com.sonyericsson.jenkins.plugins.externalresource.dispatcher.data.StashInfo;
import com.sonyericsson.jenkins.plugins.externalresource.dispatcher.data.StashResult;
import hudson.ExtensionPoint;
import hudson.model.Node;
/**
* Manager for handling reservation of resources by external services. The Method Template pattern is used to allow for
* sub-classes providing their own reservation functionality. For example the external resources on a slave might be
* managed by a daemon who handles locking and unlocking of the resources on the slave itself, and you extend this
* class to provide your own implementation of such a communication interface.
*
* @author Robert Sandell <robert.sandell@sonyericsson.com>
*/
public abstract class ExternalResourceManager implements ExtensionPoint {
/**
* The name of the manager to show the admin.
*
* @return the name.
*/
public abstract String getDisplayName();
/**
* Reserve the resource on the node. A reservation has a deadline, if the resource isn't locked until the lease
* expires the service should unlock the resource so it can be used by another build. So if the {@link
* com.sonyericsson.jenkins.plugins.externalresource.dispatcher.ExternalResourceQueueTaskDispatcher} reserves a
* resource but another {@link hudson.model.queue.QueueTaskDispatcher} vetoes the build, the resource should not
* be set to used for too long.
*
* @param node the node to communicate with.
* @param resource the resource to reserve.
* @param seconds the number of seconds the lease should be.
* @param reservedBy a String describing what reserved the resource.
* @return the result.
*/
public StashResult reserve(Node node, ExternalResource resource, int seconds, String reservedBy){
StashResult result = doReserve(node, resource, seconds, reservedBy);
if (result != null && result.isOk()) {
resource.setReserved(new StashInfo(result, reservedBy));
}
return result;
}
/**
* Implementation of the reservation mechanism itself. Sub-classes can call external sevices to do the actual locking
* if needed.
* @param node the node to communicate with.
* @param resource the resource to reserve.
* @param seconds the number of seconds the lease should be.
* @param reservedBy a String describing what reserved the resource.
* @return the result.
*/
protected abstract StashResult doReserve(Node node, ExternalResource resource, int seconds, String reservedBy);
/**
* Locks the resource (permanently) until it is unlocked, no other build should be able to use this resource.
*
* @param node the node holding the resource.
* @param resource the resource to lock.
* @param key the key to be able to lock it (retained from
* {@link #reserve(hudson.model.Node, ExternalResource, int, String)}).
* @param lockedBy a String describing what locked the resource.
* @return the result.
*/
public StashResult lock(Node node, ExternalResource resource, String key, String lockedBy){
StashResult result = doLock(node, resource, key, lockedBy);
if (result != null && result.isOk()) {
resource.setLocked(new StashInfo(result, lockedBy));
}
return result;
}
/**
* Implementation of the locking mechanism itself. Sub-classes can call external sevices to do the actual locking
* if needed.
* @param node the node holding the resource.
* @param resource the resource to lock.
* @param key the key to be able to lock it (retained from
* {@link #reserve(hudson.model.Node, ExternalResource, int, String)}).
* @param lockedBy a String describing what locked the resource.
* @return the result.
*/
protected abstract StashResult doLock(Node node, ExternalResource resource, String key, String lockedBy);
/**
* Releases the resource, other builds can now use it.
*
* @param node the node holding the resource.
* @param resource the resource to unlock.
* @param key the key to unlock the resource with (retained from a previous call to
* {@link #lock(hudson.model.Node,
* com.sonyericsson.jenkins.plugins.externalresource.dispatcher.data.ExternalResource,
* String, String)}.
* @param releasedBy a String describing what released the resource.
* @return the result.
*/
public StashResult release(Node node, ExternalResource resource, String key, String releasedBy){
StashResult result = doRelease(node, resource, key, releasedBy);
if (result != null && result.isOk()) {
resource.setReserved(null);
resource.setLocked(null);
}
return result;
}
/**
* Implementation of the releasing mechanism itself. Sub-classes can call external sevices to do the actual locking
* if needed.
* @param node the node holding the resource.
* @param resource the resource to unlock.
* @param key the key to unlock the resource with (retained from a previous call to
* {@link #lock(hudson.model.Node,
* com.sonyericsson.jenkins.plugins.externalresource.dispatcher.data.ExternalResource,
* String, String)}.
* @param releasedBy a String describing what released the resource.
* @return the result.
*/
protected abstract StashResult doRelease(Node node, ExternalResource resource, String key, String releasedBy);
/**
* Answers true if these operations are allowed using this ExternalResourceManager.
*
* @return true if allowed, false if not.
*/
public abstract boolean isExternalLockingOk();
/**
* This method should be run when there is new Metadata that the ResourceManager should know of.
*
* @param value an AbstractMetadataValue to update
*/
public abstract void updateMetadata(AbstractMetadataValue value);
}