ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jonathanhur...@apache.org
Subject ambari git commit: AMBARI-8978 - Alerts: Allow Ability To Test An AlertTarget Before Creating It (Yurii Shylov via jonathanhurley)
Date Tue, 13 Jan 2015 16:42:31 GMT
Repository: ambari
Updated Branches:
  refs/heads/trunk 2eeebfa2f -> 275e8986b


AMBARI-8978 - Alerts: Allow Ability To Test An AlertTarget Before Creating It (Yurii Shylov via jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/275e8986
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/275e8986
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/275e8986

Branch: refs/heads/trunk
Commit: 275e8986b1d45685e20676dc077fd9f8ff5bbf18
Parents: 2eeebfa
Author: Jonathan Hurley <jhurley@hortonworks.com>
Authored: Tue Jan 13 11:42:18 2015 -0500
Committer: Jonathan Hurley <jhurley@hortonworks.com>
Committed: Tue Jan 13 11:42:18 2015 -0500

----------------------------------------------------------------------
 .../AlertTargetResourceDefinition.java          |  10 ++
 .../internal/AlertTargetResourceProvider.java   |  52 ++++--
 .../notifications/NotificationDispatcher.java   |  39 ++++
 .../dispatchers/EmailDispatcher.java            |  47 ++++-
 .../dispatchers/SNMPDispatcher.java             |  76 +++++---
 .../services/AlertNoticeDispatchService.java    |   4 +-
 .../notifications/EmailDispatcherTest.java      | 117 ------------
 .../server/notifications/MockDispatcher.java    |   7 +
 .../dispatchers/EmailDispatcherTest.java        | 177 ++++++++++++++++++
 .../dispatchers/SNMPDispatcherTest.java         | 180 +++++++++++++++++++
 .../AlertNoticeDispatchServiceTest.java         |  12 ++
 11 files changed, 567 insertions(+), 154 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertTargetResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertTargetResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertTargetResourceDefinition.java
index bc0d81d..5e5079e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertTargetResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertTargetResourceDefinition.java
@@ -18,6 +18,7 @@
 package org.apache.ambari.server.api.resources;
 
 import org.apache.ambari.server.controller.spi.Resource;
+import java.util.Collection;
 
 /**
  * The {@link AlertTargetResourceDefinition} class is used to register alert
@@ -25,6 +26,8 @@ import org.apache.ambari.server.controller.spi.Resource;
  */
 public class AlertTargetResourceDefinition extends BaseResourceDefinition {
 
+  public static final String VALIDATE_CONFIG_DIRECTIVE = "validate_config";
+
   /**
    * Constructor.
    */
@@ -47,4 +50,11 @@ public class AlertTargetResourceDefinition extends BaseResourceDefinition {
   public String getSingularName() {
     return "alert_target";
   }
+
+  @Override
+  public Collection<String> getCreateDirectives() {
+    Collection<String> directives = super.getCreateDirectives();
+    directives.add(VALIDATE_CONFIG_DIRECTIVE);
+    return directives;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java
index 197e3ec..e0d9863 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java
@@ -31,6 +31,7 @@ import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.api.resources.AlertTargetResourceDefinition;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
 import org.apache.ambari.server.controller.spi.Predicate;
@@ -41,6 +42,8 @@ import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.notifications.DispatchFactory;
+import org.apache.ambari.server.notifications.NotificationDispatcher;
 import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
 import org.apache.ambari.server.orm.entities.AlertGroupEntity;
 import org.apache.ambari.server.orm.entities.AlertTargetEntity;
@@ -105,8 +108,11 @@ public class AlertTargetResourceProvider extends
   @Inject
   private static AlertDispatchDAO s_dao;
 
+  @Inject
+  private static DispatchFactory dispatchFactory;
+
   /**
-   * Used for serializationa and deserialization of some fields.
+   * Used for serialization and deserialization of some fields.
    */
   private static final Gson s_gson = new Gson();
 
@@ -126,7 +132,7 @@ public class AlertTargetResourceProvider extends
     createResources(new Command<Void>() {
       @Override
       public Void invoke() throws AmbariException {
-        createAlertTargets(request.getProperties());
+        createAlertTargets(request.getProperties(), request.getRequestInfoProperties());
         return null;
       }
     });
@@ -225,10 +231,11 @@ public class AlertTargetResourceProvider extends
    * Create and persist {@link AlertTargetEntity} from the map of properties.
    *
    * @param requestMaps
+   * @param requestInfoProps
    * @throws AmbariException
    */
   @SuppressWarnings("unchecked")
-  private void createAlertTargets(Set<Map<String, Object>> requestMaps)
+  private void createAlertTargets(Set<Map<String, Object>> requestMaps, Map<String, String> requestInfoProps)
       throws AmbariException {
     List<AlertTargetEntity> entities = new ArrayList<AlertTargetEntity>();
     for (Map<String, Object> requestMap : requestMaps) {
@@ -250,12 +257,19 @@ public class AlertTargetResourceProvider extends
             "The type of the alert target is required.");
       }
 
-      String properties = extractProperties(requestMap);
-      if (StringUtils.isEmpty(properties)) {
+      Map<String, String> properties = extractProperties(requestMap);
+
+      String propertiesJson = s_gson.toJson(properties);
+      if (StringUtils.isEmpty(propertiesJson)) {
         throw new IllegalArgumentException(
             "Alert targets must be created with their connection properties");
       }
 
+      String validationProperty =  requestInfoProps.get(AlertTargetResourceDefinition.VALIDATE_CONFIG_DIRECTIVE);
+      if (validationProperty != null && validationProperty.equalsIgnoreCase("true")) {
+        validateTargetConfig(notificationType, properties);
+      }
+
       // global not required
       boolean isGlobal = false;
       if (null != globalProperty) {
@@ -286,7 +300,7 @@ public class AlertTargetResourceProvider extends
 
       entity.setDescription(description);
       entity.setNotificationType(notificationType);
-      entity.setProperties(properties);
+      entity.setProperties(propertiesJson);
       entity.setTargetName(name);
       entity.setAlertStates(alertStateSet);
       entity.setGlobal(isGlobal);
@@ -344,7 +358,7 @@ public class AlertTargetResourceProvider extends
         entity.setNotificationType(notificationType);
       }
 
-      String properties = extractProperties(requestMap);
+      String properties = s_gson.toJson(extractProperties(requestMap));
       if (!StringUtils.isEmpty(properties)) {
         entity.setProperties(properties);
       }
@@ -448,8 +462,8 @@ public class AlertTargetResourceProvider extends
    * @return the JSON representing the key/value pairs of all properties, or
    *         {@code null} if none.
    */
-  private String extractProperties( Map<String, Object> requestMap ){
-    Map<String, Object> normalizedMap = new HashMap<String, Object>(
+  private Map<String, String> extractProperties(Map<String, Object> requestMap) {
+    Map<String, String> normalizedMap = new HashMap<String, String>(
         requestMap.size());
 
     for (Entry<String, Object> entry : requestMap.entrySet()) {
@@ -458,10 +472,26 @@ public class AlertTargetResourceProvider extends
 
       if (propCat.equals(ALERT_TARGET_PROPERTIES)) {
         String propKey = PropertyHelper.getPropertyName(key);
-        normalizedMap.put(propKey, entry.getValue());
+        normalizedMap.put(propKey, entry.getValue().toString());
       }
     }
 
-    return s_gson.toJson(normalizedMap);
+    return normalizedMap;
+  }
+
+  /**
+   * Finds dispatcher for given notification type and validates on it given alert target configuration properties.
+   * @param notificationType type of dispatcher
+   * @param properties alert target configuration properties
+   */
+  private void validateTargetConfig(String notificationType, Map<String, String> properties) {
+    NotificationDispatcher dispatcher = dispatchFactory.getDispatcher(notificationType);
+    if (dispatcher == null) {
+      throw new IllegalArgumentException("Dispatcher for given notification type doesn't exist");
+    }
+    NotificationDispatcher.ConfigValidationResult validationResult = dispatcher.validateTargetConfig(properties);
+    if (validationResult.getStatus() == NotificationDispatcher.ConfigValidationResult.Status.INVALID) {
+      throw new IllegalArgumentException(validationResult.getMessage());
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/main/java/org/apache/ambari/server/notifications/NotificationDispatcher.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/notifications/NotificationDispatcher.java b/ambari-server/src/main/java/org/apache/ambari/server/notifications/NotificationDispatcher.java
index d8c1fda..ec4093f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/notifications/NotificationDispatcher.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/notifications/NotificationDispatcher.java
@@ -17,6 +17,7 @@
  */
 package org.apache.ambari.server.notifications;
 
+import java.util.Map;
 
 /**
  * The {@link NotificationDispatcher} interface represents a mechanism for dispatching a
@@ -52,4 +53,42 @@ public interface NotificationDispatcher {
    * @return {@code true} if digest is supported, {@code false} otherwise.
    */
   public boolean isDigestSupported();
+
+  /**
+   * Validates alert target configuration. Checks if it can dispatch notifications with given properties set.
+   * @param properties alert target properties
+   * @return ConfigValidationResult with validation status and message
+   */
+  public ConfigValidationResult validateTargetConfig(Map<String, String> properties);
+
+  public static class ConfigValidationResult {
+
+    public enum Status {
+      VALID, INVALID
+    }
+
+    private String message;
+    private Status status;
+
+    private ConfigValidationResult(Status status, String message) {
+      this.message = message;
+      this.status = status;
+    }
+
+    public String getMessage() {
+      return message;
+    }
+
+    public Status getStatus() {
+      return status;
+    }
+
+    public static ConfigValidationResult valid() {
+      return new ConfigValidationResult(Status.VALID, "Configuration is valid");
+    }
+
+    public static ConfigValidationResult invalid(String message) {
+      return new ConfigValidationResult(Status.INVALID, message);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/EmailDispatcher.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/EmailDispatcher.java b/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/EmailDispatcher.java
index 289e594..67bd640 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/EmailDispatcher.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/EmailDispatcher.java
@@ -17,13 +17,16 @@
  */
 package org.apache.ambari.server.notifications.dispatchers;
 
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Timer;
 
+import javax.mail.AuthenticationFailedException;
 import javax.mail.Authenticator;
 import javax.mail.Message.RecipientType;
 import javax.mail.MessagingException;
+import javax.mail.NoSuchProviderException;
 import javax.mail.PasswordAuthentication;
 import javax.mail.Session;
 import javax.mail.Transport;
@@ -35,6 +38,7 @@ import org.apache.ambari.server.notifications.Notification;
 import org.apache.ambari.server.notifications.NotificationDispatcher;
 import org.apache.ambari.server.notifications.Recipient;
 import org.apache.ambari.server.state.alert.TargetType;
+import org.apache.ambari.server.state.services.AlertNoticeDispatchService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -159,10 +163,44 @@ public class EmailDispatcher implements NotificationDispatcher {
   }
 
   /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ConfigValidationResult validateTargetConfig(Map<String, String> properties) {
+    try {
+      Transport transport = getMailTransport(properties);
+      transport.connect();
+      transport.close();
+    } catch(AuthenticationFailedException e) {
+      LOG.debug("Invalid credentials. Authentication failure.", e);
+      return ConfigValidationResult.invalid("Invalid credentials. Authentication failure: " + e.getMessage());
+    } catch(MessagingException e) {
+      LOG.debug("Invalid config.", e);
+      return ConfigValidationResult.invalid("Invalid config: " + e.getMessage());
+    }
+    return ConfigValidationResult.valid();
+  }
+
+  protected Transport getMailTransport(Map<String, String> properties) throws NoSuchProviderException {
+    DispatchCredentials credentials = null;
+    if (properties.containsKey(AlertNoticeDispatchService.AMBARI_DISPATCH_CREDENTIAL_USERNAME)) {
+      credentials = new DispatchCredentials();
+      credentials.UserName = properties.get(AlertNoticeDispatchService.AMBARI_DISPATCH_CREDENTIAL_USERNAME);
+      credentials.Password = properties.get(AlertNoticeDispatchService.AMBARI_DISPATCH_CREDENTIAL_PASSWORD);
+    }
+    Properties props = new Properties();
+    for (Entry<String, String> entry : properties.entrySet()) {
+      props.put(entry.getKey(), entry.getValue());
+    }
+    Session session = Session.getInstance(props, new EmailAuthenticator(credentials));
+    return session.getTransport();
+  }
+
+  /**
    * The {@link EmailAuthenticator} class is used to provide a username and
    * password combination to an SMTP server.
    */
-  private static final class EmailAuthenticator extends Authenticator{
+  private static final class EmailAuthenticator extends Authenticator {
 
     private final DispatchCredentials m_credentials;
 
@@ -180,8 +218,11 @@ public class EmailDispatcher implements NotificationDispatcher {
      */
     @Override
     protected PasswordAuthentication getPasswordAuthentication() {
-      return new PasswordAuthentication(m_credentials.UserName,
-          m_credentials.Password);
+      if (m_credentials != null) {
+        return new PasswordAuthentication(m_credentials.UserName,
+            m_credentials.Password);
+      }
+      return null;
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcher.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcher.java b/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcher.java
index 6a14f1b..0ed919f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcher.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcher.java
@@ -49,6 +49,8 @@ import org.snmp4j.smi.VariableBinding;
 import org.snmp4j.transport.DefaultUdpTransportMapping;
 import org.snmp4j.util.DefaultPDUFactory;
 
+import java.util.Map;
+
 import com.google.inject.Singleton;
 
 /**
@@ -105,7 +107,7 @@ public class SNMPDispatcher implements NotificationDispatcher {
     LOG.info("Sending SNMP trap: {}", notification.Subject);
     try {
       snmp = new Snmp(new DefaultUdpTransportMapping());
-      SnmpVersion snmpVersion = getSnmpVersion(notification);
+      SnmpVersion snmpVersion = getSnmpVersion(notification.DispatchProperties);
       sendTraps(notification, snmpVersion);
       successCallback(notification);
     } catch (InvalidSnmpConfigurationException ex) {
@@ -118,6 +120,38 @@ public class SNMPDispatcher implements NotificationDispatcher {
   }
 
   /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ConfigValidationResult validateTargetConfig(Map<String, String> properties) {
+    try {
+      getDispatchProperty(properties, BODY_OID_PROPERTY);
+      getDispatchProperty(properties, SUBJECT_OID_PROPERTY);
+      getDispatchProperty(properties, TRAP_OID_PROPERTY);
+      getDispatchProperty(properties, PORT_PROPERTY);
+      SnmpVersion snmpVersion = getSnmpVersion(properties);
+      switch (snmpVersion) {
+        case SNMPv3:
+          getDispatchProperty(properties, SECURITY_USERNAME_PROPERTY);
+          TrapSecurity securityLevel = getSecurityLevel(properties);
+          switch (securityLevel) {
+            case AUTH_PRIV:
+              getDispatchProperty(properties, SECURITY_PRIV_PASSPHRASE_PROPERTY);
+            case AUTH_NOPRIV:
+              getDispatchProperty(properties, SECURITY_AUTH_PASSPHRASE_PROPERTY);
+          }
+          break;
+        case SNMPv2c:
+        case SNMPv1:
+          getDispatchProperty(properties, COMMUNITY_PROPERTY);
+      }
+    } catch (InvalidSnmpConfigurationException ex) {
+      return ConfigValidationResult.invalid(ex.getMessage());
+    }
+    return ConfigValidationResult.valid();
+  }
+
+  /**
    * Creates protocol data unit (PDU) with corresponding SNMP version for alert notification.
    * @param notification alert notification to dispatch
    * @param snmpVersion SNMP version
@@ -128,10 +162,10 @@ public class SNMPDispatcher implements NotificationDispatcher {
     PDU pdu = DefaultPDUFactory.createPDU(snmpVersion.getTargetVersion());
     pdu.setType(snmpVersion.getTrapType());
     // Set trap oid for PDU
-    pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(getDispatchProperty(notification, TRAP_OID_PROPERTY))));
+    pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(getDispatchProperty(notification.DispatchProperties, TRAP_OID_PROPERTY))));
     // Set notification body and subject for PDU objects with identifiers specified in dispatch properties.
-    pdu.add(new VariableBinding(new OID(getDispatchProperty(notification, BODY_OID_PROPERTY)), new OctetString(notification.Body)));
-    pdu.add(new VariableBinding(new OID(getDispatchProperty(notification, SUBJECT_OID_PROPERTY)), new OctetString(notification.Subject)));
+    pdu.add(new VariableBinding(new OID(getDispatchProperty(notification.DispatchProperties, BODY_OID_PROPERTY)), new OctetString(notification.Body)));
+    pdu.add(new VariableBinding(new OID(getDispatchProperty(notification.DispatchProperties, SUBJECT_OID_PROPERTY)), new OctetString(notification.Subject)));
     return pdu;
   }
 
@@ -144,7 +178,7 @@ public class SNMPDispatcher implements NotificationDispatcher {
    */
   protected void sendTraps(Notification notification, SnmpVersion snmpVersion) throws InvalidSnmpConfigurationException, IOException {
     PDU trap = prepareTrap(notification, snmpVersion);
-    String udpPort = getDispatchProperty(notification, PORT_PROPERTY);
+    String udpPort = getDispatchProperty(notification.DispatchProperties, PORT_PROPERTY);
     for (Recipient recipient : getNotificationRecipients(notification)) {
       String address = recipient.Identifier;
       Target target = createTrapTarget(notification, snmpVersion);
@@ -162,13 +196,13 @@ public class SNMPDispatcher implements NotificationDispatcher {
    */
   protected Target createTrapTarget(Notification notification, SnmpVersion snmpVersion) throws InvalidSnmpConfigurationException {
     if (snmpVersion.isCommunityTargetRequired()) {
-      OctetString community = new OctetString(getDispatchProperty(notification, COMMUNITY_PROPERTY));
+      OctetString community = new OctetString(getDispatchProperty(notification.DispatchProperties, COMMUNITY_PROPERTY));
       CommunityTarget communityTarget = new CommunityTarget();
       communityTarget.setCommunity(community);
       communityTarget.setVersion(snmpVersion.getTargetVersion());
       return communityTarget;
     } else {
-      OctetString userName = new OctetString(getDispatchProperty(notification, SECURITY_USERNAME_PROPERTY));
+      OctetString userName = new OctetString(getDispatchProperty(notification.DispatchProperties, SECURITY_USERNAME_PROPERTY));
       if (snmp.getUSM() == null) {
         // provide User-based Security Model (USM) with user specified
         USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
@@ -183,7 +217,7 @@ public class SNMPDispatcher implements NotificationDispatcher {
       }
       UserTarget userTarget = new UserTarget();
       userTarget.setSecurityName(userName);
-      userTarget.setSecurityLevel(getSecurityLevel(notification).getSecurityLevel());
+      userTarget.setSecurityLevel(getSecurityLevel(notification.DispatchProperties).getSecurityLevel());
       userTarget.setSecurityModel(SecurityModel.SECURITY_MODEL_USM);
       userTarget.setVersion(snmpVersion.getTargetVersion());
       return userTarget;
@@ -283,27 +317,27 @@ public class SNMPDispatcher implements NotificationDispatcher {
   }
 
   /**
-   * Get dispatch property with specific key from notification.
-   * @param notification alerts notification
+   * Get dispatch property with specific key from dispatch properties.
+   * @param dispatchProperties dispatch properties
    * @param key property key
    * @return property value
    * @throws InvalidSnmpConfigurationException if property with such key does not exist
    */
-  private static String getDispatchProperty(Notification notification, String key) throws InvalidSnmpConfigurationException {
-    if (notification.DispatchProperties == null || !notification.DispatchProperties.containsKey(key)) {
+  private static String getDispatchProperty(Map<String, String> dispatchProperties, String key) throws InvalidSnmpConfigurationException {
+    if (dispatchProperties == null || !dispatchProperties.containsKey(key)) {
       throw new InvalidSnmpConfigurationException(String.format("Property \"%s\" should be set.", key));
     }
-    return notification.DispatchProperties.get(key);
+    return dispatchProperties.get(key);
   }
 
   /**
-   * Returns {@link SnmpVersion} instance corresponding to dispatch property <code>ambari.dispatch.snmp.version</code> from notification.
-   * @param notification alerts notification
+   * Returns {@link SnmpVersion} instance corresponding to dispatch property <code>ambari.dispatch.snmp.version</code> from dispatch properties.
+   * @param dispatchProperties dispatch properties
    * @return corresponding SnmpVersion instance
    * @throws InvalidSnmpConfigurationException if dispatch properties doesn't contain required property
    */
-  private SnmpVersion getSnmpVersion(Notification notification) throws InvalidSnmpConfigurationException {
-    String snmpVersion = getDispatchProperty(notification, SNMP_VERSION_PROPERTY);
+  private SnmpVersion getSnmpVersion(Map<String, String> dispatchProperties) throws InvalidSnmpConfigurationException {
+    String snmpVersion = getDispatchProperty(dispatchProperties, SNMP_VERSION_PROPERTY);
     try {
       return SnmpVersion.valueOf(snmpVersion);
     } catch (IllegalArgumentException ex) {
@@ -314,13 +348,13 @@ public class SNMPDispatcher implements NotificationDispatcher {
   }
 
   /**
-   * Returns {@link TrapSecurity} instance corresponding to dispatch property <code>ambari.dispatch.snmp.security.level</code> from notification.
-   * @param notification alerts notification
+   * Returns {@link TrapSecurity} instance corresponding to dispatch property <code>ambari.dispatch.snmp.security.level</code> from dispatch properties.
+   * @param dispatchProperties dispatch properties
    * @return corresponding TrapSecurity instance
    * @throws InvalidSnmpConfigurationException if dispatch properties doesn't contain required property
    */
-  private TrapSecurity getSecurityLevel(Notification notification) throws InvalidSnmpConfigurationException {
-    String securityLevel = getDispatchProperty(notification, SECURITY_LEVEL_PROPERTY);
+  private TrapSecurity getSecurityLevel(Map<String, String> dispatchProperties) throws InvalidSnmpConfigurationException {
+    String securityLevel = getDispatchProperty(dispatchProperties, SECURITY_LEVEL_PROPERTY);
     try {
       return TrapSecurity.valueOf(securityLevel);
     } catch (IllegalArgumentException ex) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/main/java/org/apache/ambari/server/state/services/AlertNoticeDispatchService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AlertNoticeDispatchService.java b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AlertNoticeDispatchService.java
index 626799a..974dcdf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/services/AlertNoticeDispatchService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/services/AlertNoticeDispatchService.java
@@ -117,12 +117,12 @@ public class AlertNoticeDispatchService extends AbstractScheduledService {
   /**
    * The property containing the dispatch authentication username.
    */
-  private static final String AMBARI_DISPATCH_CREDENTIAL_USERNAME = "ambari.dispatch.credential.username";
+  public static final String AMBARI_DISPATCH_CREDENTIAL_USERNAME = "ambari.dispatch.credential.username";
 
   /**
    * The property containing the dispatch authentication password.
    */
-  private static final String AMBARI_DISPATCH_CREDENTIAL_PASSWORD = "ambari.dispatch.credential.password";
+  public static final String AMBARI_DISPATCH_CREDENTIAL_PASSWORD = "ambari.dispatch.credential.password";
 
   /**
    * The property containing the dispatch recipients

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/test/java/org/apache/ambari/server/notifications/EmailDispatcherTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/notifications/EmailDispatcherTest.java b/ambari-server/src/test/java/org/apache/ambari/server/notifications/EmailDispatcherTest.java
deleted file mode 100644
index c88427d..0000000
--- a/ambari-server/src/test/java/org/apache/ambari/server/notifications/EmailDispatcherTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.ambari.server.notifications;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
-import org.apache.ambari.server.state.alert.TargetType;
-import org.easymock.EasyMock;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.inject.Binder;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.google.inject.Module;
-import com.google.inject.util.Modules;
-
-/**
- *
- */
-public class EmailDispatcherTest {
-
-  private Injector m_injector;
-  private DispatchFactory m_dispatchFactory;
-
-  @Before
-  public void before() throws Exception {
-    m_injector = Guice.createInjector(Modules.override(
-        new InMemoryDefaultTestModule()).with(new MockModule()));
-
-    m_dispatchFactory = m_injector.getInstance(DispatchFactory.class);
-  }
-
-  /**
-   * Tests that an email without recipients causes a callback error.
-   */
-  @Test
-  public void testNoRecipients() {
-    Notification notification = new Notification();
-    DispatchCallback callback = EasyMock.createMock(DispatchCallback.class);
-    notification.Callback = callback;
-
-    List<String> callbackIds = new ArrayList<String>();
-    callbackIds.add(UUID.randomUUID().toString());
-    notification.CallbackIds = callbackIds;
-
-    callback.onFailure(callbackIds);
-
-    EasyMock.expectLastCall();
-    EasyMock.replay(callback);
-
-    NotificationDispatcher dispatcher = m_dispatchFactory.getDispatcher(TargetType.EMAIL.name());
-    dispatcher.dispatch(notification);
-
-    EasyMock.verify(callback);
-  }
-
-  /**
-   * Tests that an email without properties causes a callback error.
-   */
-  @Test
-  public void testNoEmailProperties() {
-    Notification notification = new Notification();
-    DispatchCallback callback = EasyMock.createMock(DispatchCallback.class);
-    notification.Callback = callback;
-    notification.Recipients = new ArrayList<Recipient>();
-
-    Recipient recipient = new Recipient();
-    recipient.Identifier = "foo";
-
-    notification.Recipients.add(recipient);
-
-    List<String> callbackIds = new ArrayList<String>();
-    callbackIds.add(UUID.randomUUID().toString());
-    notification.CallbackIds = callbackIds;
-
-    callback.onFailure(callbackIds);
-
-    EasyMock.expectLastCall();
-    EasyMock.replay(callback);
-
-    NotificationDispatcher dispatcher = m_dispatchFactory.getDispatcher(TargetType.EMAIL.name());
-    dispatcher.dispatch(notification);
-
-    EasyMock.verify(callback);
-  }
-
-  /**
-   *
-   */
-  private class MockModule implements Module {
-    /**
-     *
-     */
-    @Override
-    public void configure(Binder binder) {
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/test/java/org/apache/ambari/server/notifications/MockDispatcher.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/notifications/MockDispatcher.java b/ambari-server/src/test/java/org/apache/ambari/server/notifications/MockDispatcher.java
index 1dc7e2d..94202ca 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/notifications/MockDispatcher.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/notifications/MockDispatcher.java
@@ -17,6 +17,8 @@
  */
 package org.apache.ambari.server.notifications;
 
+import java.util.Map;
+
 /**
  *
  */
@@ -51,4 +53,9 @@ public class MockDispatcher implements NotificationDispatcher {
   @Override
   public void dispatch(Notification notification) {
   }
+
+  @Override
+  public ConfigValidationResult validateTargetConfig(Map<String, String> properties) {
+    return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/EmailDispatcherTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/EmailDispatcherTest.java b/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/EmailDispatcherTest.java
new file mode 100644
index 0000000..7522286
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/EmailDispatcherTest.java
@@ -0,0 +1,177 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.notifications.dispatchers;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.ambari.server.notifications.*;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.state.alert.TargetType;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
+
+import javax.mail.AuthenticationFailedException;
+import javax.mail.MessagingException;
+import javax.mail.Transport;
+
+/**
+ *
+ */
+public class EmailDispatcherTest {
+
+  private Injector m_injector;
+  private DispatchFactory m_dispatchFactory;
+
+  @Before
+  public void before() throws Exception {
+    m_injector = Guice.createInjector(Modules.override(
+        new InMemoryDefaultTestModule()).with(new MockModule()));
+
+    m_dispatchFactory = m_injector.getInstance(DispatchFactory.class);
+  }
+
+  /**
+   * Tests that an email without recipients causes a callback error.
+   */
+  @Test
+  public void testNoRecipients() {
+    Notification notification = new Notification();
+    DispatchCallback callback = EasyMock.createMock(DispatchCallback.class);
+    notification.Callback = callback;
+
+    List<String> callbackIds = new ArrayList<String>();
+    callbackIds.add(UUID.randomUUID().toString());
+    notification.CallbackIds = callbackIds;
+
+    callback.onFailure(callbackIds);
+
+    EasyMock.expectLastCall();
+    EasyMock.replay(callback);
+
+    NotificationDispatcher dispatcher = m_dispatchFactory.getDispatcher(TargetType.EMAIL.name());
+    dispatcher.dispatch(notification);
+
+    EasyMock.verify(callback);
+  }
+
+  /**
+   * Tests that an email without properties causes a callback error.
+   */
+  @Test
+  public void testNoEmailPropeties() {
+    Notification notification = new Notification();
+    DispatchCallback callback = EasyMock.createMock(DispatchCallback.class);
+    notification.Callback = callback;
+    notification.Recipients = new ArrayList<Recipient>();
+
+    Recipient recipient = new Recipient();
+    recipient.Identifier = "foo";
+
+    notification.Recipients.add(recipient);
+
+    List<String> callbackIds = new ArrayList<String>();
+    callbackIds.add(UUID.randomUUID().toString());
+    notification.CallbackIds = callbackIds;
+
+    callback.onFailure(callbackIds);
+
+    EasyMock.expectLastCall();
+    EasyMock.replay(callback);
+
+    NotificationDispatcher dispatcher = m_dispatchFactory.getDispatcher(TargetType.EMAIL.name());
+    dispatcher.dispatch(notification);
+
+    EasyMock.verify(callback);
+  }
+
+  @Test
+  public void testValidateTargetConfig_invalidOnAuthenticationException() throws Exception {
+
+    Map<String, String> properties = new HashMap<String, String>();
+    Transport mockedTransport = EasyMock.createNiceMock(Transport.class);
+    EmailDispatcher dispatcher = EasyMock.createMockBuilder(EmailDispatcher.class).
+        addMockedMethods("getMailTransport").createNiceMock();
+
+    EasyMock.expect(dispatcher.getMailTransport(properties)).andReturn(mockedTransport);
+    mockedTransport.connect();
+    EasyMock.expectLastCall().andThrow(new AuthenticationFailedException());
+
+    EasyMock.replay(dispatcher, mockedTransport);
+
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    Assert.assertEquals(NotificationDispatcher.ConfigValidationResult.Status.INVALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateTargetConfig_invalidOnMessagingException() throws Exception {
+
+    Map<String, String> properties = new HashMap<String, String>();
+    Transport mockedTransport = EasyMock.createNiceMock(Transport.class);
+    EmailDispatcher dispatcher = EasyMock.createMockBuilder(EmailDispatcher.class).
+        addMockedMethods("getMailTransport").createNiceMock();
+
+    EasyMock.expect(dispatcher.getMailTransport(properties)).andReturn(mockedTransport);
+    mockedTransport.connect();
+    EasyMock.expectLastCall().andThrow(new MessagingException());
+
+    EasyMock.replay(dispatcher, mockedTransport);
+
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    Assert.assertEquals(NotificationDispatcher.ConfigValidationResult.Status.INVALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateTargetConfig_validIfNoErrors() throws Exception {
+
+    Map<String, String> properties = new HashMap<String, String>();
+    Transport mockedTransport = EasyMock.createNiceMock(Transport.class);
+    EmailDispatcher dispatcher = EasyMock.createMockBuilder(EmailDispatcher.class).
+        addMockedMethods("getMailTransport").createNiceMock();
+
+    EasyMock.expect(dispatcher.getMailTransport(properties)).andReturn(mockedTransport);
+
+    EasyMock.replay(dispatcher, mockedTransport);
+
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    Assert.assertEquals(NotificationDispatcher.ConfigValidationResult.Status.VALID, configValidationResult.getStatus());
+  }
+
+  /**
+   *
+   */
+  private class MockModule implements Module {
+    /**
+     *
+     */
+    @Override
+    public void configure(Binder binder) {
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcherTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcherTest.java b/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcherTest.java
index db4af1c..ed222ed 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcherTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/notifications/dispatchers/SNMPDispatcherTest.java
@@ -19,6 +19,7 @@ package org.apache.ambari.server.notifications.dispatchers;
 
 import org.apache.ambari.server.notifications.DispatchCallback;
 import org.apache.ambari.server.notifications.Notification;
+import org.apache.ambari.server.notifications.NotificationDispatcher;
 import org.apache.ambari.server.notifications.Recipient;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -367,4 +368,183 @@ public class SNMPDispatcherTest {
     doReturn(trap).when(dispatcher).prepareTrap(notification, snmpVersion);
     dispatcher.sendTraps(notification, snmpVersion);
   }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv1() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv1");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.COMMUNITY_PROPERTY, "public");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.VALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_incorrectSNMPversion() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv4");
+    properties.put(SNMPDispatcher.COMMUNITY_PROPERTY, "public");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.INVALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv1_invalid() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv1");
+    properties.put(SNMPDispatcher.COMMUNITY_PROPERTY, "public");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.INVALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv2c() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv2c");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.COMMUNITY_PROPERTY, "public");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.VALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv2c_invalid() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv2c");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.INVALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv3_incorrectSecurityLevel() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv3");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.SECURITY_USERNAME_PROPERTY, "USER");
+    properties.put(SNMPDispatcher.SECURITY_AUTH_PASSPHRASE_PROPERTY, "PASSPHRASE1");
+    properties.put(SNMPDispatcher.SECURITY_PRIV_PASSPHRASE_PROPERTY, "PASSPHRASE2");
+    properties.put(SNMPDispatcher.SECURITY_LEVEL_PROPERTY, "INCORRECT");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.INVALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv3_noAuthNoPriv() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv3");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.SECURITY_USERNAME_PROPERTY, "USER");
+    properties.put(SNMPDispatcher.SECURITY_LEVEL_PROPERTY, "NOAUTH_NOPRIV");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.VALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv3_AuthNoPriv_valid() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv3");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.SECURITY_USERNAME_PROPERTY, "USER");
+    properties.put(SNMPDispatcher.SECURITY_AUTH_PASSPHRASE_PROPERTY, "PASSPHRASE1");
+    properties.put(SNMPDispatcher.SECURITY_LEVEL_PROPERTY, "AUTH_NOPRIV");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.VALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv3_AuthNoPriv_invalid() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv3");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.SECURITY_USERNAME_PROPERTY, "USER");
+    properties.put(SNMPDispatcher.SECURITY_LEVEL_PROPERTY, "AUTH_NOPRIV");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.INVALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv3_AuthPriv_valid() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv3");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.SECURITY_USERNAME_PROPERTY, "USER");
+    properties.put(SNMPDispatcher.SECURITY_AUTH_PASSPHRASE_PROPERTY, "PASSPHRASE1");
+    properties.put(SNMPDispatcher.SECURITY_PRIV_PASSPHRASE_PROPERTY, "PASSPHRASE2");
+    properties.put(SNMPDispatcher.SECURITY_LEVEL_PROPERTY, "AUTH_PRIV");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.VALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv3_AuthPriv_noPassphrases() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv3");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.SECURITY_USERNAME_PROPERTY, "USER");
+    properties.put(SNMPDispatcher.SECURITY_LEVEL_PROPERTY, "AUTH_PRIV");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.INVALID, configValidationResult.getStatus());
+  }
+
+  @Test
+  public void testValidateAlertValidation_SNMPv3_AuthPriv_onlyAuthPassphrase() throws Exception {
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(SNMPDispatcher.SUBJECT_OID_PROPERTY, "1");
+    properties.put(SNMPDispatcher.BODY_OID_PROPERTY, "2");
+    properties.put(SNMPDispatcher.PORT_PROPERTY, "162");
+    properties.put(SNMPDispatcher.SNMP_VERSION_PROPERTY, "SNMPv3");
+    properties.put(SNMPDispatcher.TRAP_OID_PROPERTY, "1.3.6.1.6.3.1.1.5.4");
+    properties.put(SNMPDispatcher.SECURITY_USERNAME_PROPERTY, "USER");
+    properties.put(SNMPDispatcher.SECURITY_AUTH_PASSPHRASE_PROPERTY, "PASSPHRASE1");
+    properties.put(SNMPDispatcher.SECURITY_LEVEL_PROPERTY, "AUTH_PRIV");
+    NotificationDispatcher dispatcher = new SNMPDispatcher();
+    NotificationDispatcher.ConfigValidationResult configValidationResult = dispatcher.validateTargetConfig(properties);
+    assertEquals(NotificationDispatcher.ConfigValidationResult.Status.INVALID, configValidationResult.getStatus());
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/275e8986/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java
index 1feb102..d5ab08e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/services/AlertNoticeDispatchServiceTest.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Map;
 import java.util.TimeZone;
 import java.util.UUID;
 import java.util.concurrent.Executor;
@@ -419,6 +420,11 @@ public class AlertNoticeDispatchServiceTest extends AlertNoticeDispatchService {
       m_notificaiton = notification;
     }
 
+    @Override
+    public ConfigValidationResult validateTargetConfig(Map<String, String> properties) {
+      return null;
+    }
+
     public Notification getNotification() {
       return m_notificaiton;
     }
@@ -459,6 +465,12 @@ public class AlertNoticeDispatchServiceTest extends AlertNoticeDispatchService {
     public List<Notification> getNotifications() {
       return m_notifications;
     }
+
+    @Override
+    public ConfigValidationResult validateTargetConfig(
+        Map<String, String> properties) {
+      return null;
+    }
   }
 
   /**


Mime
View raw message