Hello mooli tayer,

I'd like you to do a code review.  Please visit

    http://gerrit.ovirt.org/24707

to review the following change.

Change subject: tools: notifier: Support snmp trap as a notification method.
......................................................................

tools: notifier: Support snmp trap as a notification method.

See feature pages[1]

[1] http://www.ovirt.org/Features/engine-snmp

Change-Id: I0cd22d022ae535f45e046b09a2cbfadd837b465c
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1032661
Signed-off-by: Mooli Tayer <[email protected]>
Signed-off-by: Alon Bar-Lev <[email protected]>
---
M backend/manager/dependencies/pom.xml
A backend/manager/dependencies/src/main/modules/org/snmp4j/main/module.xml
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/EventNotificationMethod.java
M backend/manager/tools/pom.xml
M 
backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/Notifier.java
A 
backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/transport/snmp/Snmp.java
M 
backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
M ovirt-engine.spec.in
M packaging/dbscripts/upgrade/03_04_0600_event_notification_methods.sql
M packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in
M pom.xml
11 files changed, 266 insertions(+), 3 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/07/24707/1

diff --git a/backend/manager/dependencies/pom.xml 
b/backend/manager/dependencies/pom.xml
index 8e75809..7d04543 100644
--- a/backend/manager/dependencies/pom.xml
+++ b/backend/manager/dependencies/pom.xml
@@ -225,6 +225,12 @@
       <version>${aopalliance.version}</version>
     </dependency>
 
+    <dependency>
+        <groupId>org.snmp4j</groupId>
+        <artifactId>snmp4j</artifactId>
+        <version>${snmp4j.version}</version>
+    </dependency>
+
   </dependencies>
 
   <build>
@@ -441,6 +447,12 @@
                 <moduleName>org.aopalliance</moduleName>
               </module>
 
+              <module>
+                <groupId>org.snmp4j</groupId>
+                <artifactId>snmp4j</artifactId>
+                <moduleName>org.snmp4j</moduleName>
+              </module>
+
             </modules>
           </configuration>
         </plugin>
diff --git 
a/backend/manager/dependencies/src/main/modules/org/snmp4j/main/module.xml 
b/backend/manager/dependencies/src/main/modules/org/snmp4j/main/module.xml
new file mode 100644
index 0000000..e70d2d7
--- /dev/null
+++ b/backend/manager/dependencies/src/main/modules/org/snmp4j/main/module.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<module xmlns="urn:jboss:module:1.1" name="org.snmp4j">
+
+  <resources>
+    <resource-root path="snmp4j.jar"/>
+  </resources>
+
+  <dependencies>
+    <module name="org.slf4j"/>
+  </dependencies>
+
+</module>
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/EventNotificationMethod.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/EventNotificationMethod.java
index 49a9321..70254cd 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/EventNotificationMethod.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/EventNotificationMethod.java
@@ -1,5 +1,6 @@
 package org.ovirt.engine.core.common;
 
 public enum EventNotificationMethod {
-    EMAIL
+    EMAIL,
+    SNMP_TRAP
 }
diff --git a/backend/manager/tools/pom.xml b/backend/manager/tools/pom.xml
index 0f8fe63..5f22940 100644
--- a/backend/manager/tools/pom.xml
+++ b/backend/manager/tools/pom.xml
@@ -21,6 +21,12 @@
   <dependencies>
 
     <dependency>
+      <groupId>org.snmp4j</groupId>
+      <artifactId>snmp4j</artifactId>
+      <version>${snmp4j.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>${engine.groupId}</groupId>
       <artifactId>common</artifactId>
       <version>${engine.version}</version>
diff --git 
a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/Notifier.java
 
b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/Notifier.java
index 3b8e4f7..15be47c 100644
--- 
a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/Notifier.java
+++ 
b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/Notifier.java
@@ -10,6 +10,7 @@
 import org.apache.log4j.Logger;
 import org.apache.log4j.xml.DOMConfigurator;
 import org.ovirt.engine.core.notifier.transport.smtp.Smtp;
+import org.ovirt.engine.core.notifier.transport.snmp.Snmp;
 import org.ovirt.engine.core.notifier.utils.NotificationProperties;
 
 /**
@@ -57,6 +58,7 @@
             notificationService = new NotificationService(prop);
             engineMonitorService = new EngineMonitorService(prop);
             notificationService.registerTransport(new Smtp(prop));
+            notificationService.registerTransport(new Snmp(prop));
             if (!notificationService.hasTransports()) {
                 throw new RuntimeException("No transport is enabled, nothing 
to do");
             }
diff --git 
a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/transport/snmp/Snmp.java
 
b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/transport/snmp/Snmp.java
new file mode 100644
index 0000000..990cb75
--- /dev/null
+++ 
b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/transport/snmp/Snmp.java
@@ -0,0 +1,183 @@
+package org.ovirt.engine.core.notifier.transport.snmp;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.ovirt.engine.core.common.AuditLogType;
+import org.ovirt.engine.core.common.EventNotificationMethod;
+import org.ovirt.engine.core.notifier.NotificationServiceException;
+import org.ovirt.engine.core.notifier.dao.DispatchResult;
+import org.ovirt.engine.core.notifier.filter.AuditLogEvent;
+import org.ovirt.engine.core.notifier.transport.Transport;
+import org.ovirt.engine.core.notifier.utils.NotificationProperties;
+import org.snmp4j.CommunityTarget;
+import org.snmp4j.PDU;
+import org.snmp4j.mp.SnmpConstants;
+import org.snmp4j.smi.OID;
+import org.snmp4j.smi.OctetString;
+import org.snmp4j.smi.UdpAddress;
+import org.snmp4j.smi.VariableBinding;
+import org.snmp4j.transport.DefaultUdpTransportMapping;
+
+public class Snmp extends Transport {
+
+    private static final Logger log = Logger.getLogger(Snmp.class);
+
+    private static final String SNMP_MANAGERS = "SNMP_MANAGERS";
+    private static final String SNMP_COMMUNITY = "SNMP_COMMUNITY";
+    private static final String SNMP_OID = "SNMP_OID";
+    private static final int ENTERPRISE_SPECIFIC = 6;
+    private static final Pattern PROFILE_PATTERN = 
Pattern.compile(SNMP_MANAGERS + "(|_(?<profile>.*))");
+
+    private final Map<String, Profile> profiles = new HashMap<>();
+    private org.snmp4j.Snmp snmp = null;
+    private boolean active = false;
+
+    public Snmp(NotificationProperties props) {
+        for (Map.Entry<String, String> entry : 
props.getProperties().entrySet()) {
+            Matcher m = PROFILE_PATTERN.matcher(entry.getKey());
+            if (m.matches()) {
+                String profile = m.group("profile") == null ? "" : 
m.group("profile");
+                String managers = props.getProperty(SNMP_MANAGERS, profile, 
false);
+                if (!StringUtils.isBlank(managers)) {
+                    profiles.put(
+                        profile,
+                        new Profile(
+                            managers,
+                            props.getProperty(SNMP_COMMUNITY, profile, false),
+                            props.getProperty(SNMP_OID, profile, false)
+                        )
+                    );
+                }
+            }
+        }
+
+        if (!profiles.isEmpty()) {
+            try {
+                // Create a new session and define it's transport.
+                snmp = new org.snmp4j.Snmp(new DefaultUdpTransportMapping());
+            } catch (IOException e) {
+                throw new NotificationServiceException("error creating " + 
getClass().getName());
+            }
+            active = true;
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "snmp";
+    }
+
+    @Override
+    public boolean isActive() {
+        return active;
+    }
+
+    @Override
+    public void dispatchEvent(AuditLogEvent event, String address) {
+        Profile profile = profiles.get(address);
+        if (profile == null) {
+            profile = profiles.get("");
+            if (profile == null) {
+                log.warn("Could not find snmp profile: " + address);
+                return;
+            }
+        }
+
+        // PDU class is for SNMPv2c units
+        PDU v2pdu = new PDU();
+        v2pdu.setType(PDU.TRAP);
+        int auditLogTypeVal = AuditLogType.UNASSIGNED.getValue();
+        try {
+            // TODO mtayer: what about db? add to audit log type
+
+            auditLogTypeVal = AuditLogType.valueOf(event.getName()).getValue();
+        } catch (IllegalArgumentException e) {
+            log.warn("Could not find event: " + event.getName() + " in 
auditLogTypes");
+        }
+        OID trapOID = SnmpConstants.getTrapOID(profile.oid, 
ENTERPRISE_SPECIFIC, auditLogTypeVal);
+        v2pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, trapOID));
+        v2pdu.add(new VariableBinding(
+                new OID(trapOID).append(0),
+                new OctetString(event.getMessage())));
+        v2pdu.add(new VariableBinding(
+                new OID(trapOID).append(1),
+                new OctetString(event.getSeverity().name())));
+        v2pdu.add(new VariableBinding(
+                new OID(trapOID).append(2),
+                new OctetString(event.getType().name())));
+        v2pdu.add(new VariableBinding(
+                new OID(trapOID).append(3),
+                new OctetString(event.getLogTime().toString())));
+        CommunityTarget target = new CommunityTarget();
+        target.setCommunity(profile.community);
+        target.setVersion(SnmpConstants.version2c);
+        for (Host host : profile.hosts) {
+            try {
+                log.info(String.format("Generate an snmp trap for event: %s to 
address: %s ",
+                    event, host.name));
+                target.setAddress(
+                    new UdpAddress(
+                        InetAddress.getByName(host.name),
+                        host.port
+                    )
+                );
+                snmp.send(v2pdu, target);
+                notifyObservers(DispatchResult.success(event, address, 
EventNotificationMethod.SNMP_TRAP));
+            } catch (Exception e) {
+                log.error(e.getMessage());
+                notifyObservers(DispatchResult.failure(event, address, 
EventNotificationMethod.SNMP_TRAP, e.getMessage()));
+            }
+        }
+    }
+
+    private static class Host {
+        public String name;
+        public int port = 162;
+
+        public Host(String name, String port) {
+            this.name = name;
+            if (port != null) {
+                try {
+                    this.port = Integer.parseInt(port);
+                    if (this.port <= 0 || this.port > 0xffff) {
+                        throw new Exception("Bad port");
+                    }
+                } catch (Exception e) {
+                    throw new IllegalArgumentException(
+                        String.format(
+                            "Invalid port %s for snmp host %s",
+                            port,
+                            name
+                        )
+                    );
+                }
+            }
+        }
+    }
+
+    private static class Profile {
+        private static final Pattern HOST_PATTERN = 
Pattern.compile("(?<host>[^:\\s]+)(:(?<port>[^\\s]*))?");
+
+        public List<Host> hosts = new LinkedList<>();
+        public OctetString community;
+        public OID oid;
+
+        public Profile(String managers, String community, String oid) {
+            Matcher m = HOST_PATTERN.matcher(managers);
+            while (m.find()) {
+                hosts.add(new Host(m.group("host"), m.group("port")));
+            }
+            this.community = new OctetString(community);
+            this.oid = new OID(oid);
+        }
+    }
+}
diff --git 
a/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
 
b/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
index cf051a4..3f5fa07 100644
--- 
a/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
+++ 
b/backend/manager/tools/src/main/modules/org/ovirt/engine/core/tools/main/module.xml
@@ -18,6 +18,7 @@
     <module name="org.ovirt.engine.core.compat"/>
     <module name="org.ovirt.engine.core.utils"/>
     <module name="org.postgresql"/>
+    <module name="org.snmp4j"/>
     <module name="sun.jdk"/>
   </dependencies>
 
diff --git a/ovirt-engine.spec.in b/ovirt-engine.spec.in
index 0dc2932..67847f9 100644
--- a/ovirt-engine.spec.in
+++ b/ovirt-engine.spec.in
@@ -199,6 +199,7 @@
 Requires:      openstack-java-resteasy-connector >= %{openstack_java_version}
 Requires:      postgresql-jdbc
 Requires:      quartz
+Requires:      snmp4j
 Requires:      spring-ldap
 Requires:      springframework-aop
 Requires:      springframework-beans
@@ -648,6 +649,7 @@
 org/apache/xmlrpc/main/xmlrpc-common.jar
 org/postgresql/main/postgresql.jar postgresql-jdbc.jar
 org/quartz/main/quartz.jar
+org/snmp4j/main/snmp4j.jar
 org/springframework/main/spring-aop.jar springframework/spring-aop.jar
 org/springframework/main/spring-asm.jar objectweb-asm/asm.jar
 org/springframework/main/spring-beans.jar springframework/spring-beans.jar
diff --git 
a/packaging/dbscripts/upgrade/03_04_0600_event_notification_methods.sql 
b/packaging/dbscripts/upgrade/03_04_0600_event_notification_methods.sql
index 4187bc5..d515d92 100644
--- a/packaging/dbscripts/upgrade/03_04_0600_event_notification_methods.sql
+++ b/packaging/dbscripts/upgrade/03_04_0600_event_notification_methods.sql
@@ -4,7 +4,7 @@
 
 -- save EventNotificationMethod as string with constraint.
 ALTER TABLE event_subscriber ADD COLUMN notification_method CHARACTER 
VARYING(32)
-  CHECK (notification_method IN ('EMAIL'));
+  CHECK (notification_method IN ('EMAIL', 'SNMP_TRAP'));
 ALTER TABLE event_subscriber DROP CONSTRAINT pk_event_subscriber;
 ALTER TABLE event_subscriber
   ADD CONSTRAINT pk_event_subscriber PRIMARY KEY (subscriber_id, 
event_up_name, notification_method, tag_name);
diff --git 
a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in 
b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in
index 9f4ccb8..58fed0a 100644
--- a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in
+++ b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in
@@ -131,6 +131,41 @@
 # Amount of times to attempt sending an email before failing.
 MAIL_RETRIES=4
 
+#-------------------------#
+# SNMP_TRAP Notifications #
+#-------------------------#
+# Send v2c snmp notifications
+
+# Minimum SNMP configuration
+#
+# Create @ENGINE_ETC@/notifier/notifier.conf.d/20-snmp.conf with:
+# SNMP_MANAGERS="host"
+# FILTERS="include:*(snmp:) ${FILTERS}"
+
+# Default whitespace separated IP/DNS list with optional port, default is 162.
+# SNMP_MANAGERS=manager1.example.com manager2.example.com:164
+SNMP_MANAGERS=
+
+# Default SNMP Community String.
+SNMP_COMMUNITY=public
+
+# Default TRAP Object Identifier for alerts.
+#
+# 
iso.organization.DoD.Internet.private.enterprises.redhat.ovirt-engine.notifications.audit-log
+# 1.3.6.1.4.1.2312.13.1.1
+SNMP_OID=1.3.6.1.4.1.2312.13.1.1
+
+#
+# SNMP profile support
+#
+# Multiple SNMP profiles are supported.
+# Specify profile settings by using _profile suffix,
+# for example, to define a profile to sent specific
+# message to host3, specify:
+# SNMP_MANAGERS_profile1=host3
+# FILTER="include:VDC_START(snmp:profile1) ${FILTER}"
+#
+
 #----------------------------------#
 # Engine Monitoring Configuration: #
 #----------------------------------#
diff --git a/pom.xml b/pom.xml
index 24e198e..5669ef3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -92,7 +92,7 @@
     <tukaani-xz.version>1.0</tukaani-xz.version>
     <c3p0.version>0.9.1.1</c3p0.version>
     <aopalliance.version>1.0</aopalliance.version>
-
+    <snmp4j.version>2.2.2</snmp4j.version>
     <!-- OpenStack -->
     <openstack-client.version>3.0.2</openstack-client.version>
 
@@ -388,6 +388,14 @@
         <enabled>false</enabled>
       </snapshots>
     </repository>
+    <repository>
+      <id>snmp4j</id>
+      <name>snmp4j</name>
+      <url>https://oosnmp.net/dist/release/</url>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+    </repository>
   </repositories>
   <pluginRepositories>
     <pluginRepository>


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0cd22d022ae535f45e046b09a2cbfadd837b465c
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: ovirt-engine-3.4
Gerrit-Owner: Alon Bar-Lev <[email protected]>
Gerrit-Reviewer: mooli tayer <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to