View Javadoc
1   /**
2    * This Source Code Form is subject to the terms of the Mozilla Public
3    * License, v. 2.0. If a copy of the MPL was not distributed with this
4    * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5    *
6    * If it is not possible or desirable to put the notice in a particular
7    * file, then You may include the notice in a location (such as a LICENSE
8    * file in a relevant directory) where a recipient would be likely to look
9    * for such a notice.
10   *
11   * 
12   */
13  /*  ---------------------------------------------------------------------------
14   *  U.S. Government, Department of the Army
15   *  Army Materiel Command
16   *  Research Development Engineering Command
17   *  Communications Electronics Research Development and Engineering Center
18   *  ---------------------------------------------------------------------------
19   */
20  package org.miloss.fgsms.sla;
21  
22  import java.io.StringWriter;
23  import java.sql.*;
24  import java.util.UUID;
25  import javax.xml.bind.JAXBContext;
26  import javax.xml.bind.Marshaller;
27  import javax.xml.datatype.DatatypeFactory;
28  import org.miloss.fgsms.common.DBSettingsLoader;
29  import org.miloss.fgsms.common.Utility;
30  import org.miloss.fgsms.services.interfaces.common.PolicyType;
31  import org.miloss.fgsms.services.interfaces.policyconfiguration.*;
32  import org.apache.log4j.Level;
33  import org.miloss.fgsms.common.Constants;
34  import org.miloss.fgsms.common.DBUtils;
35  import org.miloss.fgsms.common.Logger;
36  
37  ;
38  
39  /**
40   * Provides helper functions for getting/setting the status of items that run
41   * outside of a web container Such as Qpid Py, Aux.Services Quartz jobs, etc
42   *
43   * @author AO most functions support pooled (JNDI) or non pooled connections via
44   * fgsms.Common
45   */
46  public class AuxHelper {
47  
48      private static Logger log = Logger.getLogger("fgsms.SLAProcessor");
49  
50      public enum FLAGS {
51  
52          AUTO_CREATE,
53          NO_AUTO_CREATE
54      }
55  
56      /**
57       * Sets the status of an item wrapper, sets policy type to status, machine
58       * name to the current machine name, and domain to unspecified, parent
59       * component to null, policies are auto created
60       *
61       * @param currenstatus
62       * @param name
63       * @param s
64       * @param pooled
65       * @deprecatedwrap
66       */
67      @Deprecated
68      public static void TryUpdateStatus(boolean currenstatus, String name, String s, boolean pooled) {
69          TryUpdateStatus(currenstatus, name, s, pooled, PolicyType.STATUS, AuxHelper.UNSPECIFIED, SLACommon.GetHostName(), null, FLAGS.AUTO_CREATE);
70      }
71  
72      /**
73       * * Sets the status of an item wrapper, sets machine name to the current
74       * machine name, and domain to unspecified, parent component to null,
75       * policies are auto created
76       *
77       * @param currenstatus
78       * @param name
79       * @param s
80       * @param pooled
81       * @param p
82       * @deprecated
83       */
84      @Deprecated
85      public static void TryUpdateStatus(boolean currenstatus, String name, String s, boolean pooled, PolicyType p) {
86          TryUpdateStatus(currenstatus, name, s, pooled, p, AuxHelper.UNSPECIFIED, SLACommon.GetHostName(), null, FLAGS.AUTO_CREATE);
87      }
88  
89      /**
90       *
91       * @param currenstatus
92       * @param name/uri of the service
93       * @param statusMessage
94       * @param pooled
95       * @param policyType
96       * @param domain
97       * @param server
98       * @param parentcomponent
99       * @param flag
100      */
101     public static void TryUpdateStatus(final boolean currenstatus, final String name, final String statusMessage, boolean pooled, final PolicyType policyType, final String domain, final String server, final String parentcomponent, final FLAGS flag) {
102         java.sql.Connection con = null;
103         java.sql.Connection perf = null;
104         PreparedStatement com = null;
105         ResultSet availset = null;
106         // end get current status
107         String oldstatusmsg = "";
108         boolean oldstatus = true;
109         boolean firstseenstatus = true;
110         try {
111             if (!pooled) {
112                 con = Utility.getConfigurationDB_NONPOOLED_Connection();
113                 perf = Utility.getPerformanceDB_NONPOOLED_Connection();
114             } else {
115                 con = Utility.getConfigurationDBConnection();
116                 perf = Utility.getPerformanceDBConnection();
117             }
118             if (flag == FLAGS.AUTO_CREATE) {
119                 CheckPolicyAndCreate(name, con, policyType, pooled, domain, server, parentcomponent);
120             }
121 
122             com = perf.prepareStatement("select * from availability where uri=? order by utcdatetime desc limit 1;");
123             com.setString(1, name);
124             availset = com.executeQuery();
125             if (availset.next()) {
126                 oldstatus = (availset.getBoolean("status"));
127                 oldstatusmsg = availset.getString("message");
128                 if (Utility.stringIsNullOrEmpty(oldstatusmsg)) {
129                     oldstatusmsg = "";
130                 }
131             }
132         } catch (Exception ex) {
133             log.log(Level.WARN, null, ex);
134         } finally {
135             DBUtils.safeClose(availset);
136             DBUtils.safeClose(com);
137         }
138         try {
139 
140             com = con.prepareStatement("select * from status  where uri=?;");
141             com.setString(1, name);
142             availset = com.executeQuery();
143             if (availset.next()) {
144                 firstseenstatus = false;
145             }
146             availset.close();
147             com.close();
148         } catch (Exception ex) {
149             log.log(Level.WARN, null, ex);
150         } finally {
151             DBUtils.safeClose(availset);
152             DBUtils.safeClose(com);
153         }
154 
155         if (firstseenstatus) {
156             PreparedStatement state = null;
157             try {
158                 //insert in status
159                 state = con.prepareStatement("INSERT INTO status(uri, utcdatetime, message, status, monitored) VALUES (?, ?, ?, ?, ?);");
160                 state.setString(1, name);
161                 state.setLong(2, System.currentTimeMillis());
162                 state.setString(3, statusMessage);
163                 state.setBoolean(4, currenstatus);
164                 state.setBoolean(5, true);
165                 state.executeUpdate();
166             } catch (Exception ex) {
167                 log.log(Level.WARN, null, ex);
168             } finally {
169                 DBUtils.safeClose(state);
170 
171             }
172             try {
173                 //insert current into perf availity
174                 state = perf.prepareStatement("INSERT INTO availability(uri, utcdatetime, id, message, status)   VALUES (?, ?, ?, ?, ?);");
175                 state.setString(1, name);
176                 state.setLong(2, System.currentTimeMillis());
177                 state.setString(3, UUID.randomUUID().toString());
178                 state.setString(4, statusMessage);
179                 state.setBoolean(5, currenstatus);
180                 state.executeUpdate();
181 
182             } catch (Exception ex) {
183                 log.log(Level.WARN, null, ex);
184             } finally {
185                 DBUtils.safeClose(state);
186             }
187 
188         } else if (currenstatus != oldstatus || !oldstatusmsg.equalsIgnoreCase(statusMessage)) {
189             //something happened, let's record it
190 
191             //update current in config status table
192             PreparedStatement state = null;
193             try {
194                 state = con.prepareStatement("UPDATE status set utcdatetime=?, message=?, status=? where uri=?;");
195                 state.setLong(1, System.currentTimeMillis());
196                 state.setString(2, statusMessage);
197                 state.setBoolean(3, currenstatus);
198                 state.setString(4, name);
199                 state.executeUpdate();
200             } catch (Exception ex) {
201                 log.log(Level.WARN, null, ex);
202             } finally {
203                 DBUtils.safeClose(state);
204 
205             }
206             try {
207 
208                 //insert current into perf availity
209                 state = perf.prepareStatement("INSERT INTO availability(uri, utcdatetime, id, message, status)   VALUES (?, ?, ?, ?, ?);");
210                 state.setString(1, name);
211                 state.setLong(2, System.currentTimeMillis());
212                 state.setString(3, UUID.randomUUID().toString());
213                 state.setString(4, statusMessage);
214                 state.setBoolean(5, currenstatus);
215                 state.executeUpdate();
216             } catch (Exception ex) {
217                 log.log(Level.WARN, null, ex);
218             } finally {
219                 DBUtils.safeClose(state);
220 
221             }
222 
223             if (currenstatus != oldstatus) {
224 
225                 SLACommon.TriggerStatusChange(name, oldstatus, oldstatusmsg, currenstatus, statusMessage, pooled);
226             }
227         } else {
228             //no change in status, just update the now timestamp to keep the ui happy
229             //update current in config status table
230             PreparedStatement state = null;
231             try {
232                 state = con.prepareStatement("UPDATE status   SET utcdatetime=? WHERE uri=?;");
233                 state.setString(2, name);
234                 state.setLong(1, System.currentTimeMillis());
235                 state.executeUpdate();
236             } catch (Exception ex) {
237                 log.log(Level.WARN, null, ex);
238             } finally {
239                 DBUtils.safeClose(state);
240 
241             }
242 
243         }
244 
245         DBUtils.safeClose(con);
246         DBUtils.safeClose(perf);
247     }
248 
249     /**
250      * Sets the status of an item, if it has changed, SLA alerts are processed
251      * data is recorded in two databases, one with the current status, and one
252      * with all previous status messages name = the URI of the item s = current
253      * status message wrapper, policies are auto created
254      *
255      * @param currenstatus
256      * @param name
257      * @param s
258      * @param pooled
259      * @param p
260      * @param domain
261      * @param server
262      * @param parentcomponent
263      */
264     public static void TryUpdateStatus(boolean currenstatus, String name, String s, boolean pooled, PolicyType p, String domain, String server, String parentcomponent) {
265         TryUpdateStatus(currenstatus, name, s, pooled, p, domain, server, parentcomponent, FLAGS.AUTO_CREATE);
266     }
267 
268     /**
269      * Sets the status of an item, if it has changed, SLA alerts are processed
270      * data is recorded in two databases, one with the current status, and one
271      * with all previous status messages name = the URI of the item s = current
272      * status message
273      *
274      * @param currenstatus
275      * @param name/uri of the thing we are setting the status on
276      * @param statusMessage message
277      * @param pooled, determines how the database connection will be loaded,
278      * pooled = JNDI lookup
279      * @param polity type
280      * @param domain, if not known, use AuxHelper.UNSPECIFIED
281      * @param server , if not known, use AuxHelper.UNSPECIFIED
282      */
283     public static void TryUpdateStatus(boolean currenstatus, String name, String statusMessage, boolean pooled, PolicyType policyType, String domain, String server) {
284         TryUpdateStatus(currenstatus, name, statusMessage, pooled, policyType, domain, server, null, FLAGS.AUTO_CREATE);
285     }//PolicyType.STATISTICAL
286 
287     /**
288      * wrapper that sets the policy type to Status
289      *
290      * @param currenstatus
291      * @param name unique name of the thing we are checking
292      * @param s current status message
293      */
294     public static void TryUpdateStatus(boolean currenstatus, String name, String s, boolean pooled, String domain, String server, FLAGS flag) {
295         TryUpdateStatus(currenstatus, name, s, pooled, PolicyType.STATUS, domain, server, null, flag);
296     }
297 
298     /**
299      * wrapper that sets the policy type to Status, auto create policy, parent
300      * component is null
301      *
302      * @param currenstatus
303      * @param name unique name of the thing we are checking
304      * @param s current status message
305      */
306     public static void TryUpdateStatus(boolean currenstatus, String name, String s, boolean pooled, String domain, String server) {
307         TryUpdateStatus(currenstatus, name, s, pooled, PolicyType.STATUS, domain, server, null, FLAGS.AUTO_CREATE);
308     }
309 
310     /**
311      * Attempts to creates a policy of the given type. Since the database has
312      * unique keys, an error messages are just swallowed up connection must be
313      * to the configuration database and be open, remains open after exiting
314      *
315      * @param uRI
316      * @param con
317      * @param pooled is not used by this function, but is passed along
318      */
319     @Deprecated
320     public static void CheckPolicyAndCreate(String URL, Connection con, PolicyType p, boolean pooled, String domainname, String hostname) {
321         CheckPolicyAndCreate(URL, con, p, pooled, domainname, hostname, null);
322     }
323 
324     /**
325      *
326      * @param URL
327      * @param con
328      * @param p
329      * @param pooled
330      * @param domainname
331      * @param hostname
332      * @param parentcomponent
333      */
334     public static void CheckPolicyAndCreate(final String URL, Connection con, final PolicyType p, boolean pooled, String domainname, String hostname, String parentcomponent) {
335         try {
336             Connection perf = null;
337             PreparedStatement c2 = null;
338             try {
339 
340                 if (pooled) {
341                     perf = Utility.getPerformanceDBConnection();
342                 } else {
343                     perf = Utility.getPerformanceDB_NONPOOLED_Connection();
344                 }
345                 c2 = perf.prepareStatement("INSERT INTO rawdatatally (URI)"
346                         + "SELECT ? WHERE NOT EXISTS"
347                         + "(SELECT uri FROM rawdatatally WHERE uri=?);");
348                 c2.setString(1, URL);
349                 c2.setString(2, URL);
350                 c2.execute();
351                 c2.close();
352                 perf.close();
353             } catch (Exception ex) {
354                 log.log(Level.WARN, SLACommon.getBundleString("ErrorInsertingRawDataTallyRecord"), ex);
355             } finally {
356                 DBUtils.safeClose(c2);
357                 DBUtils.safeClose(perf);
358             }
359             ServicePolicy policy = null;
360 
361             KeyNameValueEnc d = null;
362             long retention = Long.valueOf("31536000000");
363             switch (p) {
364                 case STATISTICAL:
365                     policy = new StatisticalServicePolicy();
366                     d = DBSettingsLoader.GetPropertiesFromDB(pooled, "Policy.Statistics", "defaultRetention");
367                     break;
368                 case STATUS:
369                     policy = new StatusServicePolicy();
370                     d = DBSettingsLoader.GetPropertiesFromDB(pooled, "Policy.Status", "defaultRetention");
371                     break;
372                 case TRANSACTIONAL:
373                     policy = new TransactionalWebServicePolicy();
374                     if (URL.toLowerCase().startsWith("http://") || URL.toLowerCase().startsWith("https://")) {
375                         ((TransactionalWebServicePolicy) policy).setBuellerEnabled(true);
376                     } else {
377                         ((TransactionalWebServicePolicy) policy).setBuellerEnabled(false);
378                     }
379                     d = DBSettingsLoader.GetPropertiesFromDB(pooled, "Policy.Transactional", "defaultRetention");
380                     break;
381                 case MACHINE:
382                     policy = new MachinePolicy();
383                     d = DBSettingsLoader.GetPropertiesFromDB(pooled, "Policy.Machine", "defaultRetention");
384                     break;
385                 case PROCESS:
386                     policy = new ProcessPolicy();
387                     d = DBSettingsLoader.GetPropertiesFromDB(pooled, "Policy.Process", "defaultRetention");
388                     break;
389             }
390             if (policy == null) {
391                 log.log(Level.ERROR, String.format(SLACommon.getBundleString("ErrorCreatingServicePolicy"), URL) + "policy type is unhandled!");
392                 throw new NullPointerException();
393             }
394             if (d != null && d.getKeyNameValue() != null) {
395                 try {
396                     retention = Long.parseLong(d.getKeyNameValue().getPropertyValue());
397                 } catch (Exception ex) {
398                     log.log(Level.WARN, String.format(SLACommon.getBundleString("ErrorUnableToParse"), "defaultRetention" + p.value(), "Long"), ex);
399                 }
400             }
401             DatatypeFactory df = DatatypeFactory.newInstance();
402             policy.setDataTTL(df.newDuration(retention));
403             policy.setDomainName(domainname);
404             policy.setMachineName(hostname);
405             policy.setPolicyType(p);
406             policy.setURL(URL);
407             policy.setParentObject(parentcomponent);
408 
409             //   UUID id = UUID.randomUUID();
410             JAXBContext jc = Utility.getSerializationContext();
411 
412             Marshaller m = jc.createMarshaller();
413             Utility.addStatusChangeSLA(policy);
414             policy.setAgentsEnabled(true);
415 
416             WritePolicytoDB(policy, URL, "system", pooled);
417 
418             SLACommon.AlertGlobalAdminsNewPolicyCreated("system", URL, pooled, p);
419         } catch (PolicyExistsException e) {
420             //in this case, the policy exists already, therefor we won't alert anyone that it was created.
421             e = e; //this is ignorable
422         } catch (Exception ex) {
423             log.log(Level.DEBUG, String.format(SLACommon.getBundleString("ErrorCreatingServicePolicy"), URL), ex);
424         }
425     }
426     public static final String UNSPECIFIED = "unspecified";
427 
428     /**
429      * Writes a service policy to the database, uses a locking mechanism to
430      * prevent duplicates First removes any existing policy then writes the
431      * policy to the db
432      *
433      * @param policy
434      * @param URL
435      * @param currentuser
436      * @param pooled
437      * @throws Exception
438      */
439     private static void WritePolicytoDB(final ServicePolicy policy, final String URL, final String currentuser, boolean pooled) throws Exception {
440         Connection con = null;
441         PreparedStatement comm = null;
442         try {
443             if (policy == null) {
444                 throw new IllegalArgumentException("policy");
445             }
446             if (policy.getPolicyType() == null) {
447                 throw new IllegalArgumentException("policy");
448             }
449             if (Utility.stringIsNullOrEmpty(URL)) {
450                 throw new IllegalArgumentException("URL");
451             }
452 
453             if (pooled) {
454                 con = Utility.getConfigurationDBConnection();
455             } else {
456                 con = Utility.getConfigurationDB_NONPOOLED_Connection();
457             }
458 
459             PreparedStatement c2 = null;
460             Connection p = null;
461             try {
462 
463                 if (pooled) {
464                     p = Utility.getPerformanceDBConnection();
465                 } else {
466                     p = Utility.getPerformanceDB_NONPOOLED_Connection();
467                 }
468                 c2 = p.prepareStatement("INSERT INTO rawdatatally (URI)"
469                         + "SELECT ? WHERE NOT EXISTS"
470                         + "(SELECT uri FROM rawdatatally WHERE uri=?);");
471                 c2.setString(1, URL);
472                 c2.setString(2, URL);
473                 c2.execute();
474 
475                 p.close();
476             } catch (Exception ex) {
477                 log.log(Level.WARN, SLACommon.getBundleString("ErrorInsertingRawDataTallyRecord"), ex);
478             } finally {
479                 DBUtils.safeClose(c2);
480                 DBUtils.safeClose(p);
481             }
482 
483             comm = con.prepareStatement("BEGIN WORK;LOCK TABLE servicepolicies IN SHARE ROW EXCLUSIVE MODE;"
484                     + "INSERT INTO servicepolicies (URI, DataTTL, " //2
485                     + " latitude, longitude, displayname, policytype, buellerenabled, hostname, domaincol, xmlpolicy, hassla, hasfederation, bucket, lastchanged, lastchangedby, "
486                     + "healthstatusenabled, parenturi )" //13
487                     + " SELECT ?,?,?,?,?,  ?,?,?,?,?, ?,?,?, ?,?,?,? WHERE NOT EXISTS"
488                     + " (SELECT uri FROM servicepolicies WHERE uri=?);" //1
489                     + ""
490                     + "COMMIT WORK;");
491 
492             comm.setString(1, URL);
493             if (policy.getDataTTL() == null) {
494                 comm.setLong(2, 30 * 24 * 60 * 60);
495             } else {
496                 comm.setLong(2, Utility.durationToTimeInMS(policy.getDataTTL()));
497             }
498             if (policy.getLocation() != null) {
499                 comm.setDouble(3, policy.getLocation().getLatitude());
500                 comm.setDouble(4, policy.getLocation().getLongitude());
501             } else {
502                 comm.setNull(3, Types.DOUBLE);
503                 comm.setNull(4, Types.DOUBLE);
504             }
505             if (Utility.stringIsNullOrEmpty(policy.getDisplayName())) {
506                 comm.setNull(5, java.sql.Types.VARCHAR);
507             } else {
508                 comm.setString(5, policy.getDisplayName());
509             }
510 
511             comm.setInt(6, policy.getPolicyType().ordinal());
512             if (policy instanceof TransactionalWebServicePolicy) {
513                 TransactionalWebServicePolicy tp = (TransactionalWebServicePolicy) policy;
514                 comm.setBoolean(7, tp.isBuellerEnabled());
515             } else {
516                 comm.setBoolean(7, false);
517             }
518 
519             if (Utility.stringIsNullOrEmpty(policy.getMachineName())) {
520                 comm.setString(8, UNSPECIFIED);
521             } else {
522                 comm.setString(8, policy.getMachineName());
523             }
524 
525             if (Utility.stringIsNullOrEmpty(policy.getDomainName())) {
526                 comm.setString(9, UNSPECIFIED);
527             } else {
528                 comm.setString(9, policy.getDomainName());
529             }
530             //xml
531             Marshaller m = Utility.getSerializationContext().createMarshaller();
532             StringWriter sw = new StringWriter();
533             m.marshal(policy, sw);
534 
535             String s = sw.toString();
536             comm.setBytes(10, s.getBytes(Constants.CHARSET));
537 
538             if (policy.getServiceLevelAggrements() != null
539                     && policy.getServiceLevelAggrements().getSLA() != null && !policy.getServiceLevelAggrements().getSLA().isEmpty()) {
540                 comm.setBoolean(11, true);
541             } else {
542                 comm.setBoolean(11, false);
543             }
544             if (policy.getFederationPolicyCollection() != null && !policy.getFederationPolicyCollection().getFederationPolicy().isEmpty()) {
545                 comm.setBoolean(12, true);
546             } else {
547                 comm.setBoolean(12, false);
548             }
549 
550             if (Utility.stringIsNullOrEmpty(policy.getBucketCategory())) {
551                 comm.setString(13, UNSPECIFIED);
552             } else {
553                 comm.setString(13, policy.getBucketCategory());
554             }
555             comm.setLong(14, System.currentTimeMillis());
556             comm.setString(15, currentuser);
557             if (policy instanceof TransactionalWebServicePolicy) {
558                 TransactionalWebServicePolicy tp = (TransactionalWebServicePolicy) policy;
559                 comm.setBoolean(16, tp.isHealthStatusEnabled());
560             } else {
561                 comm.setBoolean(16, false);
562             }
563             if (Utility.stringIsNullOrEmpty(policy.getParentObject())) {
564                 comm.setNull(17, java.sql.Types.VARCHAR);
565             } else {
566                 comm.setString(17, policy.getParentObject());
567             }
568             comm.setString(18, URL);
569             int rows = comm.executeUpdate();
570             comm.close();
571             con.close();
572             if (rows == 0) {
573                 throw new PolicyExistsException();
574             }
575             //policy inserted successfully
576             return;
577         } catch (SQLException ex) {
578             log.log(Level.ERROR, SLACommon.getBundleString("ErrorExceptionPolicyCreation") + URL, ex);
579         } catch (NullPointerException ex) {
580             log.log(Level.ERROR, SLACommon.getBundleString("ErrorExceptionPolicyCreation") + URL, ex);
581         }
582         try {
583             if (con != null && !con.isClosed()) {
584                 PreparedStatement com = con.prepareStatement("ROLLBACK WORK;");
585                 com.execute();
586                 con.close();
587             }
588         } catch (Exception ex) {
589             log.log(Level.ERROR, SLACommon.getBundleString("ErrorClosingDB"), ex);
590         } finally {
591             try {
592                 if (con != null && !con.isClosed()) {
593                     con.close();
594                 }
595             } catch (Exception ex) {
596                 log.log(Level.ERROR, SLACommon.getBundleString("ErrorClosingDB"), ex);
597             }
598         }
599         throw new PolicyExistsException();
600     }
601 
602     /**
603      * wrapper for PolicyType = Status connection must be to the configuration
604      * database and be open, remains open after exiting
605      *
606      * @param uRI
607      * @param con
608      * @param pooled is not used by this function, but is passed along
609      */
610     @Deprecated
611     public static void CheckPolicyAndCreate(String uRI, Connection con, boolean pooled, String domain, String server) {
612         CheckPolicyAndCreate(uRI, con, PolicyType.STATUS, pooled, domain, server, null);
613     }
614 
615     /**
616      *
617      * connection must be to the configuration database and be open, remains
618      * open after exiting
619      *
620      * @param uRI
621      * @param con
622      * @param pooled is not used by this function, but is passed along
623      */
624     public static void CheckStatisticalPolicyAndCreate(String uRI, Connection con, boolean pooled, String domain, String server) {
625         CheckPolicyAndCreate(uRI, con, PolicyType.STATISTICAL, pooled, domain, server, null);
626     }
627 }