/* * Lokomo OneCMDB - An Open Source Software for Configuration * Management of Datacenter Resources * * Copyright (C) 2006 Lokomo Systems AB * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. * * Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via * paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33 * Danderyd, Sweden. * */ package org.onecmdb.core.internal.job; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.onecmdb.core.IAttribute; import org.onecmdb.core.ICCBListener; import org.onecmdb.core.ICcb; import org.onecmdb.core.ICi; import org.onecmdb.core.ICmdbTransaction; import org.onecmdb.core.IJobService; import org.onecmdb.core.IJobStartResult; import org.onecmdb.core.IModelService; import org.onecmdb.core.IObjectScope; import org.onecmdb.core.IRFC; import org.onecmdb.core.IReferenceService; import org.onecmdb.core.IRfcResult; import org.onecmdb.core.IService; import org.onecmdb.core.ISession; import org.onecmdb.core.ITicket; import org.onecmdb.core.IValueProvider; import org.onecmdb.core.internal.SchemaService; import org.onecmdb.core.internal.model.Path; import org.onecmdb.core.utils.IBeanProviderSource; import org.onecmdb.core.utils.bean.CiBean; import org.onecmdb.core.utils.xml.BeanScope; import org.onecmdb.core.utils.xml.IBeanProviderConfig; import org.onecmdb.core.utils.xml.OneCmdbBeanProvider; public class JobService extends SchemaService implements IJobService, ICCBListener { private Log log; private IModelService modelService; private BeanScope initScope; private ISession initSession; private String rootJobAlias = "Job"; // Reference aliasas. private String rootTriggerReferenceAlias ="JobTriggerReference"; private String rootTriggerAlias = "JobTrigger"; private String rootCronTriggerAlias = "JobCronTrigger"; private String rootIntervallTriggerAlias = "JobIntervallTrigger"; private String rootManualTriggerAlias = "JobManualTrigger"; private String rootProcessAlias = "JobProcess"; private JobSchedulare schedulare; // / {{{ Spring IOC public void setRootAlias(String alias) { this.rootJobAlias = alias; } public void setRootTriggerAlias(String alias) { this.rootTriggerAlias = alias; } public void setRootTriggerReferenceAlias(String alias) { this.rootTriggerReferenceAlias = alias; } public void setRootCronTriggerAlias(String rootCronTriggerAlias) { this.rootCronTriggerAlias = rootCronTriggerAlias; } public void setRootIntervallTriggerAlias(String rootIntervallTriggerAlias) { this.rootIntervallTriggerAlias = rootIntervallTriggerAlias; } public void setRootManualTriggerAlias(String rootManualTriggerAlias) { this.rootManualTriggerAlias = rootManualTriggerAlias; } public void setRootProcessAlias(String rootProcessAlias) { this.rootProcessAlias = rootProcessAlias; } public void setRootJobAlias(String rootJobAlias) { this.rootJobAlias = rootJobAlias; } public void setModelService(IModelService modelService) { this.modelService = modelService; } public void setRootJobPath(String path) { this.rootJobPath = path; } public void setInitScope(BeanScope scope) { this.initScope = scope; } public void setInitSession(ISession session) { this.initSession = session; } // }} End Spring IOC public ICi getRootTrigger() { Path<String> path = new Path<String>(this.rootTriggerAlias); ICi ci = modelService.findCi(path); return (ci); } public ICi getRootTriggerReference() { Path<String> path = new Path<String>(this.rootTriggerReferenceAlias); ICi ci = modelService.findCi(path); return (ci); } public ICi getRootJob() { Path<String> path = new Path<String>(this.rootJobAlias); ICi ci = modelService.findCi(path); return (ci); } public ICi getRootIntervallTrigger() { Path<String> path = new Path<String>(this.rootIntervallTriggerAlias); ICi ci = modelService.findCi(path); return (ci); } public ICi getRootCronTrigger() { Path<String> path = new Path<String>(this.rootCronTriggerAlias); ICi ci = modelService.findCi(path); return (ci); } public ICi getRootManualTrigger() { Path<String> path = new Path<String>(this.rootManualTriggerAlias); ICi ci = modelService.findCi(path); return (ci); } public ICi getRootProcess() { Path<String> path = new Path<String>(this.rootProcessAlias); ICi ci = modelService.findCi(path); return (ci); } public void init() { if (log == null) { log = LogFactory.getLog(this.getClass()); } if (this.rootJobAlias == null) { log.fatal("No root job alias is defined."); } super.setupSchema(); this.initSession.login(); processInitScope(new InitModelProviderConfig(this.initSession)); this.initSession.logout(); setupSchedulare(); } public void close() { log.info("JobService Closing"); if (this.schedulare != null) { this.schedulare.shutdown(); } log.info("JobService Closed"); } private void setupSchedulare() { // Test start Schedulare. // TODO: Use spring IOC schedulare = new JobSchedulare(); reschedualeTriggers(initSession); // Add events from ccb, to monitor changes in schedulare... /* ICcb ccb = (ICcb) initSession.getService(ICcb.class); ccb.addChangeListener(this); */ } public void onChange(IObjectScope scope) { // handle remove of triggers... for (ICi ci : scope.getDestroyedICis()) { if (ci.isDerivedFrom(getRootTrigger())) { schedulare.cancel(ci); } } for (ICi ci : scope.getModifiedICis()) { if (ci.isDerivedFrom(getRootTrigger())) { schedulare.scheduale(initSession, ci, null); } } for (ICi ci : scope.getNewICis()) { if (ci.isDerivedFrom(getRootTrigger())) { schedulare.scheduale(initSession, ci, null); } } } /** * Serach for all Cron and Intervall * trigger's and resceduale them. * */ private void reschedualeTriggers(ISession session) { log.info("Reschedualer: Cron triggers"); reschedualeTrigger(session, getRootCronTrigger()); log.info("Reschedualer: Intervall triggers"); reschedualeTrigger(session, getRootIntervallTrigger()); } public void reschedualeTrigger(ISession session, ICi trigger) { if (trigger == null || session == null) { log.warn("Reschedualer: Session and/or trigger is null!"); return; } if (trigger.isBlueprint()) { for (ICi ci : trigger.getOffsprings()) { reschedualeTrigger(session, ci); } } else { schedulare.cancel(trigger); schedulare.scheduale(session, trigger, null); } } /** * Cancel trigger in schedualare. If trugger os template all offsprings including templates * will be canceled. * * @param trigger */ public void cancelTrigger(ISession session, ICi trigger) { if (trigger == null ) { log.warn("Reschedualer: no trigger set"); return; } if (trigger.isBlueprint()) { for (ICi ci : trigger.getOffsprings()) { cancelTrigger(session, ci); } } else { schedulare.cancel(trigger); } } private void processInitScope(IBeanProviderConfig config) { System.out.println("Process init scope:" + this.initScope); if (this.initScope != null) { if (this.initSession == null) { log.fatal("No Init session set to process init scope."); } if (this.initScope.getBeanProvider() instanceof IBeanProviderSource) { ((IBeanProviderSource)this.initScope.getBeanProvider()).setBeanProviderConfig(config); } // Set up to compare with already populated... IModelService modelService = (IModelService) this.initSession .getService(IModelService.class); OneCmdbBeanProvider oneCmdbBeanProvider = new OneCmdbBeanProvider(); oneCmdbBeanProvider.setModelService(modelService); this.initScope.setRemoteBeanProvider(oneCmdbBeanProvider); this.initScope.process(); for (CiBean bean : this.initScope.getBeanProvider().getBeans()) { modelService.addProtectedCI(bean.getAlias()); } Set<String> unresolved = this.initScope.getUnresolvedAliases(); if (unresolved.size() > 0) { log.error("Initial providers have unresolved items"); for (String alias : unresolved) { log.error(" " + alias); } throw new IllegalArgumentException("Problem importing provider files."); } List<IRFC> rfcs = this.initScope.getRFCs(); if (rfcs == null || rfcs.size() == 0) { log.info("No initial rfcs found..."); return; } // Need to send the RFC to CCB. ICcb ccb = (ICcb) initSession.getService(ICcb.class); ICmdbTransaction tx = ccb.getTx(initSession); tx.setRfc(rfcs); ITicket ticket = ccb.submitTx(tx); IRfcResult result = ccb.waitForTx(ticket); if (result.isRejected()) { log.fatal("Can't setup initial model: " + result.getRejectCause()); } else { // Update Onecmdb Configurator. config.updateConfig(); } } } private Map<IValueProvider, Set<IAttribute>> db = new HashMap<IValueProvider, Set<IAttribute>>(); private String rootJobPath; public void addProvider(IValueProvider provider, IAttribute usedFor) { Set<IAttribute> attrs = this.db.get(provider); if (attrs == null) { attrs = new HashSet<IAttribute>(1); this.db.put(provider, attrs); } attrs.add(usedFor); } /** * Run ONE turn over the registred providers * */ public void update() { for (IValueProvider provider : this.db.keySet()) { if (provider.isValid()) continue; // Object newValue = provider.fetchValueContent(); Set<IAttribute> attrs = this.db.get(provider); for (IAttribute attr : attrs) { ICmdbTransaction tx = null; // IModifiableAttribute eattr = attr.getModifiableAdaptor(tx); // eattr.setValue(newValue.toString()); } } } public Object getAdapter(Class type) { // TODO Auto-generated method stub return null; } public boolean isJob(ICi ci) { boolean isOffspring = this.modelService.isOffspringOf(getRootJob(), ci); return (isOffspring); } public JobStartResult cancelJob(ISession session, ICi process) { JobStartResult result = new JobStartResult(); if (process.isBlueprint()) { // Start all offsprings job? result.setRejectCause("Only instances of a job is cancable"); return (result); } try { // Find the interactive trigger for this job. IReferenceService refSvc = (IReferenceService) session.getService(IReferenceService.class); IModelService modSvc = (IModelService) session.getService(IModelService.class); Set<ICi> triggers = refSvc.getOriginCiReferrers(process, getRootTriggerReference()); ICi manualTrigger = null; for (ICi ci : triggers) { if (modSvc.isOffspringOf(getRootManualTrigger(), ci)) { manualTrigger = ci; break; } } if (manualTrigger == null) { result.setRejectCause("Job '" + process.getAlias() + "' can not be started manual, therefor not cancable"); return(result); } schedulare.cancel(manualTrigger); } catch (Throwable t) { log.error("Can't start job '" + process.getAlias() + "' :" + t.toString(), t); result.setRejectCause("Exception when starting job '" + process.getAlias() + "' :" + t.toString()); } return (result); } public IJobStartResult startJob(ISession session, ICi process) { JobStartResult result = new JobStartResult(); try { if (process == null || session == null) { result.setRejectCause("No session or job specified!"); return(result); } log.info("Start Job:" + process.getAlias()); if (process.isBlueprint()) { // Start all offsprings job? result.setRejectCause("Only instances of a job is startable"); return (result); } try { // Find the interactive trigger for this job. IReferenceService refSvc = (IReferenceService) session.getService(IReferenceService.class); IModelService modSvc = (IModelService) session.getService(IModelService.class); Set<ICi> triggers = refSvc.getOriginCiReferrers(process, getRootTriggerReference()); ICi manualTrigger = null; for (ICi ci : triggers) { if (modSvc.isOffspringOf(getRootManualTrigger(), ci)) { manualTrigger = ci; break; } } if (manualTrigger == null) { result.setRejectCause("Job '" + process.getAlias() + "' can not be started manual."); return(result); } schedulare.scheduale(session, manualTrigger, process); } catch (Throwable t) { log.error("Can't start job '" + process.getAlias() + "' :" + t.toString(), t); result.setRejectCause("Exception when starting job '" + process.getAlias() + "' :" + t.toString()); } return (result); } finally { log.info("Start Job Returned:" + result.toString()); } } }