All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.renci.nodeagent2.agent.server.PluginController Maven / Gradle / Ivy

The newest version!
package org.renci.nodeagent2.agent.server;

import java.util.Calendar;

import org.renci.nodeagent2.agent.config.Config;
import org.renci.nodeagent2.agent.core.PluginsRegistry;
import org.renci.nodeagent2.agent.server.error.DuplicateObjectError;
import org.renci.nodeagent2.agent.server.error.ObjectNotFoundError;
import org.renci.nodeagent2.agent.server.persistence.ScheduleEntry;
import org.renci.nodeagent2.agent.server.persistence.SchedulePersistence;
import org.renci.nodeagent2.agentlib.PluginErrorCodes;
import org.renci.nodeagent2.agentlib.PluginException;
import org.renci.nodeagent2.agentlib.PluginReturn;
import org.renci.nodeagent2.agentlib.Properties;
import org.renci.nodeagent2.agentlib.ReservationId;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PluginController {
	Log l;

	final SchedulePersistence sp;

	// remember that Spring beans are singletons (in Spring sense) by default
	@Autowired
	public PluginController(SchedulePersistence sp) {
		this.sp = sp;
		l = LogFactory.getLog(this.getClass().getName());
	}

	/**
	 * Join operation. ResponseBody forces the return object to be exactly PluginReturn (not wrapped with a model)
	 * RequestBody lets us bypass naming the parameters - simpler to call in curl and simple JSON
	 * @param name
	 * @param props
	 * @return
	 */
	@RequestMapping(value="/join/{pName}", method=RequestMethod.POST, consumes = { "application/json" })
	@ResponseBody
	public PluginReturn join(@PathVariable("pName") String name, @RequestBody Properties props) {
		try {
			Calendar future = Calendar.getInstance();
			future.add(Config.getInstance().getSchedulePeriodCalendarUnit(name), Config.getInstance().getSchedulePeriod(name));
			l.info("JOIN call to " + name + ", setting deadline to " + future.getTime());
			l.debug("  with properties " + props);
			
			PluginReturn pr = PluginsRegistry.getInstance().join(name, future.getTime(), props);
			
			if (pr == null) 
				throw new InternalError("Plugin " + name + " returned null on join");
			
			if (pr.getStatus() == PluginErrorCodes.OK.code) {
				// insert the renew event into the database with initial and returned properties 
				// the deadline is set to the execution deadline (schedule period - tick advance)
				ScheduleEntry se = sp.findEntry(name, pr.getResId().getId());
				
				if (se != null)
					throw new DuplicateObjectError("Plugin " + name + " reservation with id " + pr.getResId() + " already exists!");

				l.info("Updating the database for " + name + " new reservation " + pr.getResId());
				sp.saveRenewDeadline(name, future.getTime(), pr.getResId(), props, pr.getProperties(), 0, null);
			} else {
				l.error("JOIN returned an error " + pr.getStatus() + " " + pr.getErrorMsg());
				throw new InternalError("JOIN returned an error " + pr.getStatus() + " " + pr.getErrorMsg());
			}
			
			return pr;
		} catch (PluginException pe) {
			l.error("PluginError invoking join on " + name + ": " + pe);
			return new PluginReturn(PluginErrorCodes.EXCEPTION.code, "join error: " + pe.getMessage(), null, null);
		} catch (InternalError ie) {
			throw ie;
		} catch (DuplicateObjectError doe) {
			throw doe;
		} catch (Exception e) {
			l.error("Error invoking join on " + name + ": " + e);
			throw new InternalError("Error invoking join on " + name + ": " + e);
		}	
	}

	@RequestMapping(value="/leave/{pName}/{resId:.+}", method=RequestMethod.POST, consumes = { "application/json" })
	@ResponseBody 
	public PluginReturn leave(@PathVariable(value="pName") String name, @PathVariable(value="resId") String resId, @RequestBody Properties props) {
		ReservationId rid = new ReservationId(resId);
		try {
			l.info("LEAVE call to " + name + " for " + rid);
			l.debug("  with properties " + props);
			
			// get the lock
			PluginsRegistry.getInstance().acquire(name, rid);
			
			l.info("Removing from the database");
			ScheduleEntry se = sp.removeEntry(name, rid);
			
			if (se == null)
				throw new ObjectNotFoundError("No schedule entries found in the NA2 database for " + name + " reservation " + resId);
			
			PluginReturn pr = PluginsRegistry.getInstance().leave(name, rid, props, se.getSchedProperties());
			
			if (pr == null) 
				throw new InternalError("Plugin returned null");
			
			l.info("LEAVE call to " + name + " for " + rid + " returned " + pr.getStatus() + " " + pr.getErrorMsg());
			return pr;
		} catch (PluginException pe) {
			l.error("PluginError invoking leave on " + name + ": " + pe);
			return new PluginReturn(PluginErrorCodes.EXCEPTION.code, "leave error: " + pe.getMessage(), rid, null);
		} catch (InternalError ie) {
			throw ie;
		} catch (DuplicateObjectError doe) {
			throw doe;
		} catch (Exception e) {
			l.error("Error invoking leave on " + name + ": " + e);
			throw new InternalError("Error invoking leave on " + name + ": " + e);
		} finally {
			PluginsRegistry.getInstance().release(name, rid);
		}
	}

	@RequestMapping(value="/modify/{pName}/{resId:.+}", method=RequestMethod.POST, consumes = { "application/json" })
	@ResponseBody
	public PluginReturn modify(@PathVariable(value="pName") String name, @PathVariable(value="resId") String resId, @RequestBody Properties props) {
		ReservationId rid = new ReservationId(resId);
		try {
			l.info("MODIFY call to " + name + " for " + rid);
			l.debug("  with properties " + props);
			// get the lock
			PluginsRegistry.getInstance().acquire(name, rid);
			
			ScheduleEntry se = sp.findEntry(name, resId);
			
			if (se == null)
				throw new ObjectNotFoundError("No schedule entries found in the NA2 database for " + name + " reservation " + resId);
			
			PluginReturn pr = PluginsRegistry.getInstance().modify(name, rid, props, se.getSchedProperties());
			
			if (pr == null) 
				throw new InternalError("Plugin returned null");
			
			l.info("MODIFY call to " + name + " for " + rid + " returned " + pr.getStatus() + " " + pr.getErrorMsg());
			return pr;
		} catch (PluginException pe) {
			l.error("PluginError invoking modify on " + name + ": " + pe);
			return new PluginReturn(PluginErrorCodes.EXCEPTION.code, "modify error: " + pe.getMessage(), rid, null);
		} catch (InternalError ie) {
			throw ie;
		} catch (DuplicateObjectError doe) {
			throw doe;
		} catch (Exception e) {
			l.error("Error invoking modify on " + name + ": " + e);
			throw new InternalError("Error invoking modify on " + name + ": " + e);
		} finally {
			PluginsRegistry.getInstance().release(name, rid);
		}
	}

	@RequestMapping(value="/status/{pName}/{resId:.+}", method=RequestMethod.GET)
	public PluginReturn status(@PathVariable(value="pName") String name, @PathVariable(value="resId") String resId) {
		ReservationId rid = new ReservationId(resId);
		try {
			l.info("STATUS call to " + name + " reservation " + resId);
			ScheduleEntry se = sp.findEntry(name, resId);
			
			if (se == null)
				throw new ObjectNotFoundError("No schedule entries found in the NA2 database for " + name + " reservation " + resId);
			
			return PluginsRegistry.getInstance().status(name, rid,
					(se != null ? se.getSchedProperties() : null));
		} catch (PluginException pe) {
			l.error("PluginError getting status for " + name + ": " + pe.getMessage());
			return new PluginReturn(PluginErrorCodes.EXCEPTION.code, "status error: error getting status for " + name + ": " + pe.getMessage(), 
					rid, null);
		} catch (InternalError ie) {
			throw ie;
		} catch (DuplicateObjectError doe) {
			throw doe;
		} catch (Exception e) {
			l.error("Error getting status for " + name + ": " + e.getMessage());
			throw new InternalError("Error getting status for " + name + ": " + e.getMessage());
		}
	}

	@RequestMapping(value="/description/{pName}", method=RequestMethod.GET)
	public String description(@PathVariable(value="pName") String name) {
		try {
			l.info("DESCRIPTION call to " + name);
			String desc = PluginsRegistry.getInstance().getDescription(name);
			if (desc == null)
				return "No description provided for " + name;
			else
				return desc;
		} catch (PluginException pe) {
			l.error("PluginError getting description for " + name + ": " + pe.getMessage());
			return "PluginError getting description for " + name + ": " + pe.getMessage();
		} catch (InternalError ie) {
			throw ie;
		} catch (DuplicateObjectError doe) {
			throw doe;
		} catch (Exception e) {
			l.error("Error getting description for " + name + ": " + e.getMessage());
			throw new InternalError("Error getting description for " + name + ": " + e.getMessage());
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy