001    /*
002     * $RCSfile: SchedulerCommandLine.java,v $ 
003     *
004     * Created on December 23, 2002, 11:30 AM
005     *
006     * This file is part of the STAR Scheduler.
007     * Copyright (c) 2002-2006 STAR Collaboration - Brookhaven National Laboratory
008     *
009     * STAR Scheduler is free software; you can redistribute it and/or modify
010     * it under the terms of the GNU General Public License as published by
011     * the Free Software Foundation; either version 2 of the License, or
012     * (at your option) any later version.
013     *
014     * STAR Scheduler is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017     * GNU General Public License for more details.
018     *
019     * You should have received a copy of the GNU General Public License
020     * along with STAR Scheduler; if not, write to the Free Software
021     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
022     */
023    package gov.bnl.star.offline.scheduler;
024    
025    import gov.bnl.star.offline.scheduler.util.ConfigToolkit;
026    import gov.bnl.star.offline.scheduler.util.persistent.SiteConfigGen;
027    import gov.bnl.star.offline.scheduler.informationService.Proxy;
028    
029    import java.util.Map;
030    //import java.util.logging.FileHandler;
031    //import java.util.logging.Handler;
032    //import java.util.logging.Level;
033    import org.apache.log4j.Logger;
034    import java.util.Date; 
035    import java.util.Calendar;
036    import java.util.StringTokenizer;
037    
038    
039    import org.apache.log4j.Level;
040    import org.apache.log4j.Logger;
041    import org.apache.log4j.SimpleLayout; //may not be used 
042    import org.apache.log4j.PatternLayout;
043    import org.apache.log4j.FileAppender;
044    
045    
046    /** Used for parsing options passes to the scheduler via the command line. 
047     * @author  Gabriele Carcassi & Pavel Jakl
048     * @version $Revision: 1.66 $ $Date: 2006/11/21 00:41:32 $
049     */
050    public class SchedulerCommandLine {
051        static private Logger log = Logger.getLogger(SchedulerCommandLine.class.getName());
052        
053        protected void defaultComponent() {
054            init = "defaultJobInitializer";//ComponentLibrary.getInstance().getJobInitializer();
055            //policy = "defaultPolicy";// ComponentLibrary.getInstance().getPolicy();
056            dispatcher = "defaultDispatcher";// ComponentLibrary.getInstance().getDispatcher();
057        }
058        
059        public static String getProgramName() {
060            return "STAR Scheduler Beta 1.8.x";
061        }
062    
063        protected String init;
064        protected String policy;
065        protected String dispatcher;
066        
067        private String configfile = null;
068        
069        private boolean loggerSet = false;
070        
071        
072    
073        /** Creates a new Scheduler*/
074        private Scheduler createScheduler() {
075            return new Scheduler(getJobInitializer(), getPolicy(), getDispatcher());
076        }
077    
078        protected Level getLoggingLevel() {
079            return Level.OFF;
080        }
081        
082        /** Display the usage of the scheduler. */
083        protected void usage() {
084            System.out.println();
085            System.out.println("Usage: star-submit <xmlJobDescription>");
086            System.out.println();
087            System.out.println("For more information about how to use the " +
088                "STAR scheduler, you can consult the online documentation at: ");
089            System.out.println("-> http://www.star.bnl.gov/STAR/comp/Grid/scheduler/");
090            System.out.println("For help or feedback, you can use the scheduler " +
091                "discussion list at: ");
092            System.out.println(
093                "-> http://www.star.bnl.gov/HyperNews-star/get/scheduler.html");
094        }
095    
096        private void runScheduler(String[] args) {
097            System.out.println(getProgramName());
098            System.out.println("*** Note: The default directory in which jobs start has be fix to $SCRATCH ***");
099    
100            defaultComponent();
101    
102            String xmlFile = null;
103            try {
104                xmlFile = parseOptions(args);
105            } catch (Exception e) {
106                //TODO Think about exception handling!
107                System.exit(-1);
108            }
109            
110            
111            if(! ConfigToolkit.getToolkit().localSiteExists()){
112                //System.out.println("Could not find description of this site in the config file. Please check that the -site option is configured correctly.");
113                //System.exit(-1);
114                
115                SiteConfigGen.loadLocalSiteConfig(configfile);
116            }
117            
118            
119            
120            //load the proxy for this site if any.
121            Site site = ConfigToolkit.getToolkit().myLocalSite();
122            if(site != null){
123                Proxy proxy = site.getProxy();
124                if(proxy != null){
125                    proxy.installProxy();
126                }
127            }
128            
129            
130            /*
131            
132            // Setting the log detail on the standard output
133            Handler[] handlers = Logger.getLogger("").getHandlers();
134    
135            for (int index = 0; index < handlers.length; index++) {
136                handlers[index].setFormatter(new LogFormatter());
137                handlers[index].setLevel(getLoggingLevel());
138            }
139    
140            Logger.getLogger("").setLevel(getLoggingLevel());
141             */
142            
143            if(! loggerSet) setFileLogging();
144    
145            Scheduler scheduler = createScheduler();
146            
147            Date date = new Date();
148            
149            try { 
150                log.info("Version :\"" + getProgramName() + "\" Run at : " + date.toString() + " run on host " + java.net.InetAddress.getLocalHost().getHostName() + " ");
151            } catch (Exception e) { 
152                log.info("Version :\"" + getProgramName() + "\" Run at : " + date.toString() + " ");
153            }
154            
155            //System.out.println("\n\n host >>>>>" + java.net.InetAddress.getLocalHost().getHostName());
156            
157            log.info("XML file is: " + xmlFile + "");
158    
159            try {
160                scheduler.submit(xmlFile);
161                System.out.println("Scheduling successful");
162            } catch (Exception e) {
163                System.out.println("Scheduling failed!");
164                System.out.println(e.getMessage());
165                //log.log(Level.SEVERE, "Scheduler.submit failed", e);
166                log.fatal("Scheduler.submit failed" + e.toString()   );
167            }
168             
169             
170        }
171        
172        public static void main(String[] args) {
173            new SchedulerCommandLine().runScheduler(args);
174        }
175    
176        private boolean isOption(String text) {
177            return text.startsWith("-");
178        }
179        
180        
181        public void setScreenLogging(String debugLevel){
182          
183            
184            String loggingFormat = "%p-%l:%n%m%n%n";
185            PatternLayout layout = new PatternLayout(loggingFormat);
186            
187            java.util.Enumeration appenders = log.getRootLogger().getAllAppenders();
188            while(appenders .hasMoreElements()   ){
189                org.apache.log4j.Appender appender = (org.apache.log4j.Appender) appenders.nextElement();
190                appender.setLayout(layout);
191            }
192            
193            //levels : DEBUG, INFO, WARN, ERROR and FATAL
194            log.getRootLogger().setLevel((Level) Level.toLevel(debugLevel));
195            
196            loggerSet = true;
197            
198        }
199        
200        
201        public void setFileLogging() {
202            
203    
204          Map logConf = ConfigToolkit.getToolkit().myLocalSite().getLogConf();
205              if(logConf == null){
206                 System.out.println("Warning the configuration block in the local site is not set !"); 
207                 return ;
208              }
209          
210          String logDir = (String) logConf.get("directory");
211          
212          if ((!logDir.endsWith("/")) || (!logDir.endsWith("\\"))){
213              logDir = logDir + '/';
214          }
215          
216          String logFile = logDir + System.getProperty("user.name") + ".log";
217          
218          String loggingFormat = "%p-%l:%n%m%n%n";
219          PatternLayout layout = new PatternLayout(loggingFormat);
220          
221          
222          Logger rootLogger = log.getRootLogger();
223          log.getRootLogger().removeAllAppenders();
224          //get the logging level from the config file and set it.
225          rootLogger.setLevel((Level) Level.toLevel((String) logConf.get("level")));
226          
227          try { 
228              rootLogger.addAppender(new FileAppender(layout,logFile,false));
229              System.out.println("Your Log file can be found at: " + logFile);
230          }catch(Exception e) {
231                System.out.println("Failed to add logging appender\n" + e.toString() );
232                e.printStackTrace();
233          }
234          
235          loggerSet = true;
236           
237        }
238        
239        
240        
241    /*
242        public void setFileLogging() {
243            
244    //        Map logConf = (Map) ComponentLibrary.getInstance().getComponent("log"); //this has been moved to become part of the site object
245              Map logConf = ConfigToolkit.getToolkit().myLocalSite().getLogConf();
246              if(logConf == null){
247                 System.out.println("Warning the configuration block in the local site is not set !"); 
248                 //return ;
249              }
250            
251            
252            String logDir = (String) logConf.get("directory");
253            String levelName = (String) logConf.get("level");
254            Level level;
255            try {
256                level = (Level) Level.class.getDeclaredField(levelName).get(null);
257            } catch (Exception e) {
258                level = Level.FINER;
259                System.out.println("WARNING: Couldn't find specified loggin level:\n"+e.getMessage());
260                System.out.println("  Using default (FINER)");
261            }
262            
263            if ((!logDir.endsWith("/")) || (!logDir.endsWith("\\"))) {
264                logDir = logDir + '/';
265            }
266    
267            String userName = System.getProperty("user.name");
268            //Date date = new Date();
269            //StringTokenizer st = new StringTokenizer(date.toString()," ",false);
270            //String dateTag="";
271            //while (st.hasMoreElements()) dateTag += st.nextElement();
272            
273            String logFile = logDir + userName + ".log";
274    
275            try {
276                Handler fh = new FileHandler(logFile, true);
277                Logger.getLogger("").addHandler(fh);
278                fh.setFormatter(new LogFormatter());
279                Logger.getLogger("").setLevel(level);
280                log.config("Beginning to log on file : " + logFile);
281            } catch (Exception e) {
282                System.out.println("WARNING: Couldn't open log file.");
283    
284                return;
285            }
286        }
287     
288     */
289        
290        String parseOptions(String[] args) {
291            String xmlFile = null;
292            for (int nArg = 0; nArg < args.length; nArg++) {
293                if (isOption(args[nArg]) && (nArg != (args.length - 1))) {
294                    parseOption(args[nArg], args[nArg + 1]);
295                    nArg++;
296                } else if (nArg == (args.length - 1)) {
297                    xmlFile = args[nArg];
298                } else {
299                    System.out.println("Wrong use of the command.");
300                    usage();
301                    throw new RuntimeException();
302                }
303            }
304            
305            if (xmlFile == null) {
306                usage();
307                throw new RuntimeException();
308            }
309    
310            return xmlFile;
311        }
312    
313        boolean configSet = false; //True if the config is set
314        
315        private void parseOption(String option, String value) {
316            if (option.equals("-conf")) {
317                ComponentLibrary.initLibrary(value);
318                
319                configfile = value;
320    
321                log.info("Reading configuration file " + value);
322                configSet = true;
323                return;
324            }
325            
326            if (option.equals("-p") || option.equals("-policy")) {  
327                if(value.matches(".*/.*")){
328                    ConfigToolkit.getToolkit().addGlobalObject("DYNO_SITE_FLAG", value.replaceAll(".*/(.*)","$1"));
329                    policy =  value.replaceAll("(.*)/.*","$1");   
330                    return;
331                }
332                policy = value;
333                return;
334            }
335    
336            if (option.equals("-dispatcher")) {
337                System.out.println("\nWarning : The \"dispatcher\" option will be deprecated.");
338                dispatcher = value;
339                return;
340            }
341            
342            
343            if (option.equals("-debug")) {
344                
345                               //////////////////////////////////loging options/////////////////////////////////////////////
346                    if(value.equals("debug")  ){
347                        setScreenLogging("DEBUG");
348                        return;
349                    }
350                    else if(value.equals("info")){
351                        setScreenLogging("INFO");
352                        return;
353                    }
354                    else if(value.equals("warn")){
355                        setScreenLogging("WARN");
356                        return;
357                    }
358                    else if(value.equals("error")){
359                        setScreenLogging("ERROR");
360                        return;
361                    }
362                    else if(value.equals("fatal")){
363                        setScreenLogging("FATAL");
364                        return;
365                    }
366                    else{
367                        System.out.println("\nThe value of -debug \"" + value + "\" is not supported."); 
368                        System.out.println("Use: -debug [debug, info, warn, error or, fatal] \n example:  star-submit -debug info myjob.xml\n");
369                        throw new RuntimeException();
370                    }
371            }
372            
373            
374        
375     
376            
377            if (option.equals("-u")) {
378                if(configSet){
379                    if(value.equals("grid")){
380                        ComponentLibrary.getInstance().forceGridDispatchers();
381                        //String forceGrid = "true"; //any objetc 
382                        //ComponentLibrary.getInstance().addComponent("SUMS_FLAG_FORCE_GRID", forceGrid);
383                        ConfigToolkit.getToolkit().setFlag("SUMS_FLAG_FORCE_GRID");
384                        return;
385                    }
386                    else if(value.equals("nqc")){
387                       // String noQueueCheck = "true"; //any objetc 
388                        //ComponentLibrary.getInstance().addComponent("SUMS_FLAG_DO_NO_QUEUE_CHECK", noQueueCheck);
389                        ConfigToolkit.getToolkit().setFlag("SUMS_FLAG_DO_NO_QUEUE_CHECK");
390                        return;
391                    }
392                    else if(value.equals("ie")){
393                        ConfigToolkit.getToolkit().setFlag("SUMS_FLAG_IGNORE_ERRORS");
394                        return;
395                    }
396                    System.out.println("\nThe value of \"" + value + "\" is not supported."); 
397                }else{
398                    System.out.println("The -config [configFile] option must come before any other parameter is passed. Please contact the system administrator to correct this miss-configuration.");
399                    throw new RuntimeException("The config [configFile] option must come before any other parameter is passed. Please contact the system administrator to correct this miss-configuration.");
400                }
401            }
402            
403            
404            
405            if (option.equals("-site")) { //By putting this in the ComponentLibrary all objects can read it.
406                
407                if(configSet){
408                    if(ComponentLibrary.getInstance().getComponent("localSite") == null){
409                        ComponentLibrary.getInstance().addComponent("localSite", value);
410                    }
411                    else System.out.println("Using site : " + ((String) ComponentLibrary.getInstance().getComponent("localSite")) ); 
412                    return;
413                }
414                else{
415                    System.out.println("The -config [configFile] option must come before any other parameter is passed. Please contact the system administrator to correct this miss-configuration.");
416                    throw new RuntimeException("The config [configFile] option must come before any other parameter is passed. Please contact the system administrator to correct this miss-configuration.");
417                }         
418                
419            }
420            
421    
422            
423            System.out.println("Option " + option + " not recognized. Aborting...");
424            throw new RuntimeException();
425        }
426        
427        JobInitializer getJobInitializer() {
428            return (JobInitializer) getComponent(init, JobInitializer.class, "JobInitializer");
429        }
430        
431        Policy getPolicy() {
432            if(policy != null) return (Policy) getComponent(policy, Policy.class, "policy");
433            else return ConfigToolkit.getToolkit().myLocalSite().getDefaultPolic();
434        }
435        
436        Dispatcher getDispatcher() {
437            return (Dispatcher) getComponent(dispatcher, Dispatcher.class, "dispatcher");
438        }
439        
440        
441        private Object getComponent(String name, Class type, String typeName) {
442            
443            Object component = ComponentLibrary.getInstance().getComponent(name);
444            
445            if((component == null) && (type == Dispatcher.class)){ //
446                return new gov.bnl.star.offline.scheduler.GenericCompositeDispatcher();
447            }
448            
449            if (component != null) {
450                if (type.isInstance(component)) {
451                    if (!name.startsWith("default")) {
452                        System.out.println("Using scheduling " + typeName + ": " + name);
453                    }
454                    return component;
455                } else {
456                    // TODO Exception UserMessage: probably used the wrong option for the class
457                    log.fatal("An object " + name + " was found but was not a "+typeName+". Aborting...");
458                    System.out.println("Can't find "+typeName+" "+name+". Aborting...");
459                    throw new RuntimeException();
460                }
461            } else {
462                // TODO Exception UserMessage: probably mistyped the dispatcher
463                log.fatal(typeName + " " + name + " was not found in the configuration. Aborting...");
464                System.out.println("Can't find "+typeName+" "+name+". Aborting...");
465                throw new RuntimeException();
466            }
467        }
468        
469       
470        
471        
472        
473        //Stop all Dispatcher from submitting  
474        public void stop(){
475            Dispatcher dispatcher = getDispatcher();
476            dispatcher.stop();
477       
478        }
479        
480        
481        
482    }