/**
* Copyright (C) 2015 Orange
* 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 com.francetelecom.clara.cloud.paas.activation;
import com.francetelecom.clara.cloud.commons.NotFoundException;
import com.francetelecom.clara.cloud.commons.tasks.PollTaskStateInterface;
import com.francetelecom.clara.cloud.commons.tasks.TaskStatus;
import com.francetelecom.clara.cloud.commons.tasks.TaskStatusEnum;
import com.francetelecom.clara.cloud.commons.xstream.XStreamUtils;
import com.francetelecom.clara.cloud.coremodel.ActivationContext;
import com.francetelecom.clara.cloud.model.ModelItem;
import com.francetelecom.clara.cloud.model.ModelItemRepository;
import com.thoughtworks.xstream.XStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Base class that defines the contract that the plugin providers need to meet
* to plug into the activation process.
*
* An ActivationPlugin class takes responsibility for the life-cycle by
* inspecting the ModelItem in the accept() method. Then it is invoked during
* the various life cycle steps.
*
* Note that ActivationPlugin subclasses need to be stateless and thread-safe: a
* single instance is called is concurrence for all process activations.
*
* TODO: confirm persistence strategy: The persistent data such as subscriptions
* may be stored in the TDI, or in the TaskStatus
*/
public abstract class ActivationPlugin<T extends ModelItem> implements PollTaskStateInterface<TaskStatus> {
protected static Logger logger = LoggerFactory.getLogger(ActivationPlugin.class);
@Autowired
protected ModelItemRepository modelItemRepository;
public TaskStatus init(int entityId, final Class<T> entityClass) throws NotFoundException {
return init(
(T) modelItemRepository.find(entityId, entityClass));
}
/**
* Activate the TDI
*
* @param entityId The JPA identifier of the model Entity associated with this plugin
* (e.g. ApplicationServerInstance if the plugin responded true in the {@link #accept(Class, ActivationStepEnum)} method)
* @param context
* A string that identify environment: it's dedicated to Xaas to
* tag resources
* @return A TaskStatus
* @throws NotFoundException
* If entity is not found
*/
public TaskStatus activate(int entityId, final Class<T> entityClass, ActivationContext context) throws NotFoundException {
return activate(
(T) modelItemRepository.find(entityId, entityClass),
context);
}
public TaskStatus firststart(int entityId, final Class<T> entityClass) throws NotFoundException {
return firststart(
(T) modelItemRepository.find(entityId, entityClass));
}
public TaskStatus start(int entityId, final Class<T> entityClass) throws NotFoundException {
return start(
(T) modelItemRepository.find(entityId, entityClass));
}
public TaskStatus stop(int entityId, final Class<T> entityClass) throws NotFoundException {
return stop(
(T) modelItemRepository.find(entityId, entityClass));
}
/**
* See {@link #delete(com.francetelecom.clara.cloud.model.ModelItem)} }
*/
public TaskStatus delete(int entityId, final Class<T> entityClass) throws NotFoundException {
return delete(
(T) modelItemRepository.find(entityId, entityClass));
}
/**
* Called before creation. This task must be asynchronous and return fast.
* This task is used to check runtime dependencies
*
* @param entity
* The entity to init
* @return A TaskStatus to check task status
*/
public TaskStatus init(final T entity) {
// This should not be called but it's possible
logger.warn("This plugin method should not be called (" + this.getClass().getName() + "::init is missing)");
TaskStatus status = new TaskStatus();
status.setTaskStatus(TaskStatusEnum.FINISHED_OK);
status.setPercent(100);
return status;
}
/**
* Called for resource creation (e.g. upon completion the resource is created but not started).
* This task must be asynchronous and return fast.
*
* @param entity
* The entity to activate
* @param context
* A string that identify environment: it's dedicated to Xaas to
* tag resources
* @return A TaskStatus to check task status
*/
public TaskStatus activate(final T entity, ActivationContext context) {
// This should not be called but it's possible
logger.warn("This plugin method should not be called " + this.getClass().getName() + "::activate");
TaskStatus status = new TaskStatus();
status.setTaskStatus(TaskStatusEnum.FINISHED_OK);
status.setPercent(100);
return status;
}
/**
* Called for first start so you can configure your entity and start it.
* This task must be asynchronous and return fast.
*
* @param entity
* The entity to start
* @return A TaskStatus to check task status
*/
public TaskStatus firststart(final T entity) {
// This should not be called but it's possible
logger.warn("This plugin method should not be called " + this.getClass().getName() + "::firststart");
TaskStatus status = new TaskStatus();
status.setTaskStatus(TaskStatusEnum.FINISHED_OK);
status.setPercent(100);
return status;
}
/**
* Called for start so you must start your entity. This task must be
* asynchronous and return fast.
*
* @param entity
* The entity to start
* @return A TaskStatus to check task status
*/
public TaskStatus start(final T entity) {
// This should not be called but it's possible
logger.warn("This plugin method should not be called " + this.getClass().getName() + "::start");
TaskStatus status = new TaskStatus();
status.setTaskStatus(TaskStatusEnum.FINISHED_OK);
status.setPercent(100);
return status;
}
/**
* Called for stop so you must stop your entity. This task must be
* asynchronous and return fast.
*
* @param entity
* The entity to stop
* @return A TaskStatus to check task status
*/
public TaskStatus stop(final T entity) {
// This should not be called but it's possible
logger.warn("This plugin method should not be called " + this.getClass().getName() + "::stop");
TaskStatus status = new TaskStatus();
status.setTaskStatus(TaskStatusEnum.FINISHED_OK);
status.setPercent(100);
return status;
}
/**
* Called for deletion of a resource. This task must be asynchronous and return fast.
*
* Should also be idempotent:
* <ol>
* <li>If the delete() request previously completed successfully and the next delete() requests should complete
* successfully (i.e. delete() should ignore request if entity(tdi) is in DELETED state)</li>
* <li>If the real-life resource is missing (e.g. no corresponding dbaas instance or cf space, because of an
* inconsistency between elpaaso view and real-life-view),
* the delete() request should complete successfully.</li>
* </ol>
*
* Should however prevent resource leaks, and report a failure when a real-life resource exists which fails to be deleted:
* <ol>
* <li>If the remote resource's broker is temporary unavailable, unreacheable, times-out, or returns a 500 error,
* this method should return a TaskStatus with a failure completion, potentially after rechecking the resource
* is still present,or retrying the delete.</li>
* </ol>
*
*
* @param entity
* The entity to delete
* @return A TaskStatus to check task status
*
*/
public TaskStatus delete(final T entity) {
// This should not be called but it's possible
logger.warn("This plugin method should not be called " + this.getClass().getName() + "::delete");
TaskStatus status = new TaskStatus();
status.setTaskStatus(TaskStatusEnum.FINISHED_OK);
status.setPercent(100);
return status;
}
/**
* Does this plugin want to be called for this entity at this step?
*
* @param entityClass
* The entity
* @param step
* The step
* @return true if this plugin wants to be called for this entity at this
* step
*/
public abstract boolean accept(Class<?> entityClass, ActivationStepEnum step);
public abstract TaskStatus giveCurrentTaskStatus(TaskStatus taskStatus);
protected String dumpToXmlForTraces(ModelItem modelItem) {
XStream xStream = XStreamUtils.instanciateXstreamForHibernate();
return xStream.toXML(modelItem);
}
}