Upgrade to latest oparent
[aaf/authz.git] / authz-batch / src / main / java / com / att / authz / Batch.java
1 /*******************************************************************************
2  * Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
3  *******************************************************************************/
4 package com.att.authz;
5
6 import java.io.File;
7 import java.io.FileInputStream;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.PrintStream;
12 import java.lang.reflect.Constructor;
13 import java.net.InetAddress;
14 import java.net.URL;
15 import java.net.UnknownHostException;
16 import java.nio.ByteBuffer;
17 import java.text.SimpleDateFormat;
18 import java.util.GregorianCalendar;
19 import java.util.HashSet;
20 import java.util.Properties;
21 import java.util.Set;
22 import java.util.TimeZone;
23
24 import org.apache.log4j.Logger;
25
26 import com.att.authz.env.AuthzEnv;
27 import com.att.authz.env.AuthzTrans;
28 import com.att.authz.org.Organization;
29 import com.att.authz.org.OrganizationException;
30 import com.att.authz.org.OrganizationFactory;
31 import com.att.dao.CassAccess;
32 import org.onap.aaf.inno.env.APIException;
33 import org.onap.aaf.inno.env.Env;
34 import org.onap.aaf.inno.env.StaticSlot;
35 import org.onap.aaf.inno.env.TimeTaken;
36 import org.onap.aaf.inno.env.impl.Log4JLogTarget;
37 import org.onap.aaf.inno.env.log4j.LogFileNamer;
38 import com.datastax.driver.core.Cluster;
39 import com.datastax.driver.core.ResultSet;
40 import com.datastax.driver.core.Row;
41 import com.datastax.driver.core.Session;
42 import com.datastax.driver.core.Statement;
43
44 public abstract class Batch {
45         private static StaticSlot ssargs;
46
47         protected static final String STARS = "*****";
48
49     protected final Cluster cluster; 
50     protected static AuthzEnv env;
51     protected static Session session;
52     protected static Logger aspr;
53     private static Set<String> specialNames = null;
54     protected static boolean dryRun; 
55         protected static String batchEnv;
56
57         public static final String CASS_ENV = "CASS_ENV";
58     protected final static String PUNT="punt";
59     protected final static String VERSION="VERSION";
60     public final static String GUI_URL="GUI_URL";
61     
62     protected final static String ORA_URL="ora_url";
63     protected final static String ORA_PASSWORD="ora_password";
64
65
66     
67     protected Batch(AuthzEnv env) throws APIException, IOException {
68         // TODO  - Property Driven Organization
69 //      try {
70 //                      // att = new ATT(env);
71 //              } catch (OrganizationException e) {
72 //                      throw new APIException(e);
73 //              }
74
75         // Be able to change Environments
76         // load extra properties, i.e.
77         // PERF.cassandra.clusters=....
78         batchEnv = env.getProperty(CASS_ENV);
79         if(batchEnv != null) {
80                 batchEnv = batchEnv.trim();
81                 env.info().log("Redirecting to ",batchEnv,"environment");
82                 String str;
83                 for(String key : new String[]{
84                                 CassAccess.CASSANDRA_CLUSTERS,
85                                 CassAccess.CASSANDRA_CLUSTERS_PORT,
86                                 CassAccess.CASSANDRA_CLUSTERS_USER_NAME,
87                                 CassAccess.CASSANDRA_CLUSTERS_PASSWORD,
88                                 VERSION,GUI_URL,PUNT,
89                                 // TEMP
90                                 ORA_URL, ORA_PASSWORD
91                                 }) {
92                         if((str = env.getProperty(batchEnv+'.'+key))!=null) {
93                             env.setProperty(key, str);
94                         }
95                 }
96         }
97
98         // Setup for Dry Run
99         cluster = CassAccess.cluster(env,batchEnv);
100         env.info().log("cluster name - ",cluster.getClusterName());
101         String dryRunStr = env.getProperty( "DRY_RUN" );
102         if ( dryRunStr == null || dryRunStr.equals("false") ) {
103                     dryRun = false;
104                 } else {
105             dryRun = true;
106             env.info().log("dryRun set to TRUE");
107         }
108
109         // Special names to allow behaviors beyond normal rules
110         String names = env.getProperty( "SPECIAL_NAMES" );
111         if ( names != null )
112         {
113             env.info().log("Loading SPECIAL_NAMES");
114             specialNames = new HashSet<String>();
115             for (String s :names.split(",") )
116             {
117                 env.info().log("\tspecial: " + s );
118                 specialNames.add( s.trim() );
119             }
120         }
121     }
122
123     protected abstract void run(AuthzTrans trans);
124     protected abstract void _close(AuthzTrans trans);
125     
126     public String[] args() {
127         return (String[])env.get(ssargs);
128     }
129         
130     public boolean isDryRun()
131     {
132         return( dryRun );
133     }
134     
135         public boolean isSpecial(String user) {
136                 if (specialNames != null && specialNames.contains(user)) {
137                         env.info().log("specialName: " + user);
138
139                         return (true);
140                 } else {
141                         return (false);
142                 }
143         }
144         
145         public boolean isMechID(String user) {
146                 if (user.matches("m[0-9][0-9][0-9][0-9][0-9]")) {
147                         return (true);
148                 } else {
149                         return (false);
150                 }
151         }
152
153         protected PrintStream fallout(PrintStream _fallout, String logType)
154                         throws IOException {
155                 PrintStream fallout = _fallout;
156                 if (fallout == null) {
157                         File dir = new File("logs");
158                         if (!dir.exists()) {
159                                 dir.mkdirs();
160                         }
161
162                         File f = null;
163                         // String os = System.getProperty("os.name").toLowerCase();
164                         long uniq = System.currentTimeMillis();
165
166                         f = new File(dir, getClass().getSimpleName() + "_" + logType + "_"
167                                         + uniq + ".log");
168
169                         fallout = new PrintStream(new FileOutputStream(f, true));
170                 }
171                 return fallout;
172         }
173
174         public Organization getOrgFromID(AuthzTrans trans, String user) {
175                 Organization org;
176                 try {
177                         org = OrganizationFactory.obtain(trans.env(),user.toLowerCase());
178                 } catch (OrganizationException e1) {
179                         trans.error().log(e1);
180                         org=null;
181                 }
182
183                 if (org == null) {
184                         PrintStream fallout = null;
185
186                         try {
187                                 fallout = fallout(fallout, "Fallout");
188                                 fallout.print("INVALID_ID,");
189                                 fallout.println(user);
190                         } catch (Exception e) {
191                                 env.error().log("Could not write to Fallout File", e);
192                         }
193                         return (null);
194                 }
195
196                 return (org);
197         }
198         
199         public static Row executeDeleteQuery(Statement stmt) {
200                 Row row = null;
201                 if (!dryRun) {
202                         row = session.execute(stmt).one();
203                 }
204
205                 return (row);
206
207         }
208         
209         public static int acquireRunLock(String className) {
210                 Boolean testEnv = true;
211                 String envStr = env.getProperty("AFT_ENVIRONMENT");
212
213                 if (envStr != null) {
214                         if (envStr.equals("AFTPRD")) {
215                                 testEnv = false;
216                         }
217                 } else {
218                         env.fatal()
219                                         .log("AFT_ENVIRONMENT property is required and was not found. Exiting.");
220                         System.exit(1);
221                 }
222
223                 if (testEnv) {
224                         env.info().log("TESTMODE: skipping RunLock");
225                         return (1);
226                 }
227
228                 String hostname = null;
229                 try {
230                         hostname = InetAddress.getLocalHost().getHostName();
231                 } catch (UnknownHostException e) {
232                         e.printStackTrace();
233                         env.warn().log("Unable to get hostname");
234                         return (0);
235                 }
236
237                 ResultSet existing = session.execute(String.format(
238                                 "select * from authz.run_lock where class = '%s'", className));
239
240                 for (Row row : existing) {
241                         long curr = System.currentTimeMillis();
242                         ByteBuffer lastRun = row.getBytesUnsafe(2); // Can I get this field
243                                                                                                                 // by name?
244
245                         long interval = (1 * 60 * 1000); // @@ Create a value in props file
246                                                                                                 // for this
247                         long prev = lastRun.getLong();
248
249                         if ((curr - prev) <= interval) {
250                                 env.warn().log(
251                                                 String.format("Too soon! Last run was %d minutes ago.",
252                                                                 ((curr - prev) / 1000) / 60));
253                                 env.warn().log(
254                                                 String.format("Min time between runs is %d minutes ",
255                                                                 (interval / 1000) / 60));
256                                 env.warn().log(
257                                                 String.format("Last ran on machine: %s at %s",
258                                                                 row.getString("host"), row.getDate("start")));
259                                 return (0);
260                         } else {
261                                 env.info().log("Delete old lock");
262                                 deleteLock(className);
263                         }
264                 }
265
266                 GregorianCalendar current = new GregorianCalendar();
267
268                 // We want our time in UTC, hence "+0000"
269                 SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss+0000");
270                 fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
271
272                 String cql = String
273                                 .format("INSERT INTO authz.run_lock (class,host,start) VALUES ('%s','%s','%s') IF NOT EXISTS",
274                                                 className, hostname, fmt.format(current.getTime()));
275
276                 env.info().log(cql);
277
278                 Row row = session.execute(cql).one();
279                 if (!row.getBool("[applied]")) {
280                         env.warn().log("Lightweight Transaction failed to write lock.");
281                         env.warn().log(
282                                         String.format("host with lock: %s, running at %s",
283                                                         row.getString("host"), row.getDate("start")));
284                         return (0);
285                 }
286                 return (1);
287         }
288         
289     private static void deleteLock( String className) {
290         Row row = session.execute( String.format( "DELETE FROM authz.run_lock WHERE class = '%s' IF EXISTS", className ) ).one();
291         if (! row.getBool("[applied]")) {
292             env.info().log( "delete failed" );
293         }
294     }
295
296     private static void transferVMProps(AuthzEnv env, String ... props) {
297                 String value;
298                 for(String key : props) {
299                         if((value = System.getProperty(key))!=null) {
300                             env.setProperty(key, value);
301                         }
302                 }
303                 
304         }
305         
306         protected int count(String str, char c) {
307                 int count=str==null||str.isEmpty()?0:1;
308                 for(int i=str.indexOf(c);i>=0;i=str.indexOf(c,i+1)) {
309                         ++count;
310                 }
311                 return count;
312         }
313
314         public final void close(AuthzTrans trans) {
315             _close(trans);
316             cluster.close();
317         }
318
319         public static void main(String[] args) {
320                 Properties props = new Properties();
321                 InputStream is=null;
322                 String filename;
323                 String propLoc;
324                 try {
325                     File f = new File("etc/authBatch.props");
326                     try {
327                         if(f.exists()) {
328                                 filename = f.getCanonicalPath();
329                             is = new FileInputStream(f);
330                             propLoc=f.getPath();
331                         } else {
332                             URL rsrc = ClassLoader.getSystemResource("authBatch.props");
333                             filename = rsrc.toString();
334                             is = rsrc.openStream();
335                             propLoc=rsrc.getPath();
336                         }
337                         props.load(is);
338                     } finally {
339                         if(is==null) {
340                             System.err.println("authBatch.props must exist in etc dir, or in Classpath");
341                             System.exit(1);
342                         }
343                         is.close();
344                     }
345                 
346                     env = new AuthzEnv(props);
347                     
348                     transferVMProps(env,CASS_ENV,"DRY_RUN","NS","Organization");
349                                 
350                     // Flow all Env Logs to Log4j, with ENV
351                     
352                         LogFileNamer lfn;
353                         if((batchEnv=env.getProperty(CASS_ENV))==null) {
354                                 lfn = new LogFileNamer("logs/").noPID();
355                         } else {
356                                 lfn = new LogFileNamer("logs/" + batchEnv+'/').noPID();
357                         }
358                         
359                         lfn.setAppender("authz-batch");
360                         lfn.setAppender("aspr|ASPR");
361                         lfn.setAppender("sync");
362                         lfn.setAppender("jobchange");
363                         lfn.setAppender("validateuser");
364                         aspr = Logger.getLogger("aspr");
365                     Log4JLogTarget.setLog4JEnv("authz-batch", env);
366                     if(filename!=null) {
367                         env.init().log("Instantiated properties from",filename);
368                     }
369         
370                                 
371                     // Log where Config found
372                     env.info().log("Configuring from",propLoc);
373                     propLoc=null;
374                 
375                     Batch batch = null;
376                     // setup ATTUser and Organization Slots before starting this:
377                     //TODO Property Driven Organization
378 //                  env.slot(ATT.ATT_USERSLOT);
379 //                  OrganizationFactory.setDefaultOrg(env, ATT.class.getName());
380                     AuthzTrans trans = env.newTrans();
381                     
382                     TimeTaken tt = trans.start("Total Run", Env.SUB);
383                     try {
384                         int len = args.length;
385                         if(len>0) {
386                                 String toolName = args[0];
387                                 len-=1;
388                                 if(len<0)len=0;
389                                 String nargs[] = new String[len];
390                                 if(len>0) {
391                                         System.arraycopy(args, 1, nargs, 0, len);
392                                 }
393                                 
394                                 env.put(ssargs=env.staticSlot("ARGS"), nargs);
395                                 
396                             /*
397                              * Add New Batch Programs (inherit from Batch) here
398                              */
399         
400                             if( JobChange.class.getSimpleName().equals(toolName)) {
401                                 aspr.info( "Begin jobchange processing" );
402                                 batch = new JobChange(trans);
403                             }
404         ////                    else if( ValidateUsers.class.getSimpleName().equals(toolName)) {
405         ////                        aspr.info( "Begin ValidateUsers processing" );
406         ////                        batch = new ValidateUsers(trans);
407         //                    }
408                             else if( UserRoleDataGeneration.class.getSimpleName().equals(toolName)) {
409                                 // This job duplicates User Role add/delete History items 
410                                 // so that we can search them by Role. Intended as a one-time
411                                 // script! but written as batch job because Java has better
412                                 // UUID support. Multiple runs will generate multiple copies of 
413                                 // these history elements!
414                                 aspr.info( "Begin User Role Data Generation Processing ");
415                                 batch = new UserRoleDataGeneration(trans);
416                             } else {  // Might be a Report, Update or Temp Batch
417                                 Class<?> cls;
418                                 String classifier = "";
419                                 try {
420                                         cls = ClassLoader.getSystemClassLoader().loadClass("com.att.authz.update."+toolName);
421                                         classifier = "Update:";
422                                 } catch(ClassNotFoundException e) {
423                                         try {
424                                                 cls = ClassLoader.getSystemClassLoader().loadClass("com.att.authz.reports."+toolName);
425                                                 classifier = "Report:";
426                                         } catch (ClassNotFoundException e2) {
427                                                 try {
428                                                         cls = ClassLoader.getSystemClassLoader().loadClass("com.att.authz.temp."+toolName);
429                                                 classifier = "Temp Utility:";
430                                                 } catch (ClassNotFoundException e3) {
431                                                         cls = null;
432                                                 }
433                                         }
434                                 }
435                                 if(cls!=null) {
436                                         Constructor<?> cnst = cls.getConstructor(new Class[]{AuthzTrans.class});
437                                         batch = (Batch)cnst.newInstance(trans);
438                                         env.info().log("Begin",classifier,toolName);
439                                 }
440                             }
441         
442                             if(batch==null) {
443                                 trans.error().log("No Batch named",toolName,"found");
444                             }
445                             /*
446                              * End New Batch Programs (inherit from Batch) here
447                              */
448         
449                         } 
450                         if(batch!=null) {
451                             batch.run(trans);
452                         }
453                     } finally {
454                         tt.done();
455                         if(batch!=null) {
456                             batch.close(trans);
457                         }
458                         StringBuilder sb = new StringBuilder("Task Times\n");
459                         trans.auditTrail(4, sb, AuthzTrans.REMOTE);
460                         trans.info().log(sb);
461                     }
462                 } catch (Exception e) {
463                     e.printStackTrace(System.err);
464                     // Exceptions thrown by DB aren't stopping the whole process.
465                     System.exit(1);
466                 }
467             }
468
469
470 }
471