mooli tayer has uploaded a new change for review.

Change subject: Notification service should send a notification when Database 
is down.
......................................................................

Notification service should send a notification when Database is down.

Send a notification email after first failure to fetch notifications,
and then once every failedQueriesNotificationThreshold times (new conf 
parameter).

The recipients is also a conf value, FAILED_QUERIES_NOTIFICATION_RECIPIENTS.
A comma seperated email list is expected.
If it is empty no notifications are sent on db connection failure.

Change-Id: Id0d36b6140846bf98a33064cc69a9a398a8d4128
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=971324
Signed-off-by: Mooli Tayer <mta...@redhat.com>
---
M 
backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java
M 
backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/utils/NotificationProperties.java
M packaging/conf/notifier.conf.defaults.in
3 files changed, 88 insertions(+), 4 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/68/15768/1

diff --git 
a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java
 
b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java
index b44070e..f6c898e 100644
--- 
a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java
+++ 
b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java
@@ -1,5 +1,6 @@
 package org.ovirt.engine.core.notifier;
 
+import java.net.ConnectException;
 import java.sql.CallableStatement;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -9,14 +10,16 @@
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.Date;
+import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 import javax.sql.DataSource;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
+import org.ovirt.engine.core.common.AuditLogSeverity;
 import org.ovirt.engine.core.common.EventNotificationMethods;
 import org.ovirt.engine.core.common.businessentities.DbUser;
 import org.ovirt.engine.core.common.businessentities.EventAuditLogSubscriber;
@@ -46,12 +49,17 @@
     private NotificationMethodFactoryMapper methodsMapper = null;
     private int daysToKeepHistory = 0;
     private int daysToSendOnStartup = 0;
+    private EventSender failedQueriesEventSender;
+    private List<EventAuditLogSubscriber> failedQueriesEventSubscribers = 
Collections.emptyList();
+    private int failedQueriesNotificationThreshold;
+    private int failedQueries = 0;
 
     public NotificationService(NotificationProperties prop) throws 
NotificationServiceException {
         this.prop = prop;
         initConnectivity();
         initConfigurationProperties();
         initEvents();
+        initFailedQueriesEventSubscribers();
     }
 
     /**
@@ -60,13 +68,23 @@
      * Validated properties are: <li>DAYS_TO_KEEP_HISTORY - property could be 
omitted, if specified should be a positive
      * <li>INTERVAL_IN_SECONDS - property is mandatory, if specified should be 
a positive <li>DB Connectivity
      * Credentials - if failed to obtain connection to database, fails
+     * <li>FAILED_QUERIES_NOTIFICATION_THRESHOLD - send db connectivity 
notification once every x query attempts.
+     *
      * @throws NotificationServiceException
      *             configuration setting error
      */
     private void initConfigurationProperties() throws 
NotificationServiceException {
         daysToKeepHistory = 
getNonNegativeIntegerProperty(NotificationProperties.DAYS_TO_KEEP_HISTORY);
         daysToSendOnStartup = 
getNonNegativeIntegerProperty(NotificationProperties.DAYS_TO_SEND_ON_STARTUP);
+        failedQueriesNotificationThreshold =
+                
getNonNegativeIntegerProperty(NotificationProperties.FAILED_QUERIES_NOTIFICATION_THRESHOLD);
+        if (failedQueriesNotificationThreshold == 0) {
+            failedQueriesNotificationThreshold = 1;
+        }
         initMethodMapper();
+        failedQueriesEventSender =
+                methodsMapper.getMethod(EventNotificationMethods.EMAIL);
+        
     }
 
     private int getNonNegativeIntegerProperty(final String name) throws 
NotificationServiceException {
@@ -215,7 +233,7 @@
         Connection connection = null;
         PreparedStatement ps = null;
         ResultSet rs = null;
-        List<EventAuditLogSubscriber> eventSubscribers  = new 
ArrayList<EventAuditLogSubscriber>();
+        List<EventAuditLogSubscriber> eventSubscribers  = new ArrayList<>();
         try {
             connection = ds.getConnection();
             ps =
@@ -226,16 +244,22 @@
             while (rs.next()) {
                 eventSubscribers.add(getEventAuditLogSubscriber(rs));
             }
+
+        } catch (SQLException e) {
+            if (isConnectionException(e)){
+                handleQueryFailure();
+            }
+            throw e;
         } finally {
             DbUtils.closeQuietly(rs, ps, connection);
         }
-        DbUser dbUser = null;
+        DbUser dbUser;
         for (EventAuditLogSubscriber eventSubscriber:eventSubscribers) {
             dbUser = getUserByUserId(eventSubscriber.getsubscriber_id());
             if (dbUser != null) {
                 EventSender method =
                         
methodsMapper.getMethod(EventNotificationMethods.forValue(eventSubscriber.getmethod_id()));
-                EventSenderResult sendResult = null;
+                EventSenderResult sendResult;
                 try {
                     sendResult = method.send(eventSubscriber, 
dbUser.getemail());
                 } catch (Exception e) {
@@ -250,6 +274,26 @@
                 updateAuditLogEventProcessed(eventSubscriber);
             }
         }
+    }
+
+    private boolean isConnectionException(SQLException e) {
+        return e.getCause() instanceof ConnectException;
+    }
+
+    private void handleQueryFailure() {
+        if (failedQueries == 0) {
+            try {
+                for( EventAuditLogSubscriber 
failedQueriesEventSubscriber:failedQueriesEventSubscribers){
+                    failedQueriesEventSubscriber.setlog_time(new Date());
+                    failedQueriesEventSender.
+                            send(failedQueriesEventSubscriber, 
failedQueriesEventSubscriber.getmethod_address());
+                }
+            } catch (Exception e) {
+                log.error("Failed to dispatch query failure email message", e);
+                // Don't rethrow. we don't want to mask the original query 
exception.
+            }
+        }
+        failedQueries = (failedQueries + 1) % 
failedQueriesNotificationThreshold;
     }
 
     private void updateAuditLogEventProcessed(EventAuditLogSubscriber 
eventSubscriber) throws SQLException {
@@ -355,4 +399,23 @@
         return eals;
     }
 
+    private void initFailedQueriesEventSubscribers() {
+        String emailRecipients = 
prop.getProperty(NotificationProperties.FAILED_QUERIES_NOTIFICATION_RECIPIENTS, 
true);
+        if (StringUtils.isEmpty(emailRecipients)) {
+            return;
+        }
+        List<EventAuditLogSubscriber> failedQueriesEventSubscribers = new 
LinkedList<>();
+        for (String email:emailRecipients.split(",")){
+            EventAuditLogSubscriber eals = new EventAuditLogSubscriber();
+            eals.setevent_type(0);
+            eals.setevent_up_name("DATABASE_UNREACHABLE");
+            eals.setmethod_id(EventNotificationMethods.EMAIL.getValue());
+            eals.setmethod_address(StringUtils.strip(email));
+            eals.setmessage("Failed to query for notifications. Database 
Connection refused.");
+            eals.setseverity(AuditLogSeverity.ERROR.getValue());
+            failedQueriesEventSubscribers.add(eals);
+        }
+        this.failedQueriesEventSubscribers = failedQueriesEventSubscribers;
+    }
+
 }
diff --git 
a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/utils/NotificationProperties.java
 
b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/utils/NotificationProperties.java
index c26179f..6886a21 100644
--- 
a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/utils/NotificationProperties.java
+++ 
b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/utils/NotificationProperties.java
@@ -52,6 +52,18 @@
      */
     public static final String DAYS_TO_SEND_ON_STARTUP = 
"DAYS_TO_SEND_ON_STARTUP";
 
+    /**
+     * Comma separated list of recipients to be informed in case
+     * the notification service cannot connect to the DB. can be empty.
+     */
+    public static final String FAILED_QUERIES_NOTIFICATION_RECIPIENTS = 
"FAILED_QUERIES_NOTIFICATION_RECIPIENTS";
+
+    /**
+     * Send a notification email after first failure to fetch notifications,
+     * and then once every failedQueriesNotificationThreshold times.
+     */
+    public static final String FAILED_QUERIES_NOTIFICATION_THRESHOLD = 
"FAILED_QUERIES_NOTIFICATION_THRESHOLD";
+
     private static final Logger log = 
Logger.getLogger(NotificationProperties.class);
 
     // Default files for defaults and overridden values:
diff --git a/packaging/conf/notifier.conf.defaults.in 
b/packaging/conf/notifier.conf.defaults.in
index eaee7cd..dc9c291 100644
--- a/packaging/conf/notifier.conf.defaults.in
+++ b/packaging/conf/notifier.conf.defaults.in
@@ -68,6 +68,15 @@
 # messages will be sent at all during startup.
 DAYS_TO_SEND_ON_STARTUP=0
 
+# Send a notification email after first failure to fetch notifications,
+# and then once every failedQueriesNotificationThreshold times.
+# 0 or 1 means notify on each failure.
+FAILED_QUERIES_NOTIFICATION_THRESHOLD=30
+
+# Comma separated list of email recipients to be informed in case
+# the notification service cannot connect to the DB. can be empty.
+FAILED_QUERIES_NOTIFICATION_RECIPIENTS=
+
 #----------------------------------#
 # Engine Monitoring Configuration: #
 #----------------------------------#


-- 
To view, visit http://gerrit.ovirt.org/15768
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id0d36b6140846bf98a33064cc69a9a398a8d4128
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: mooli tayer <mta...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to