/**
* 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.io.IOException;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.apache.ambari.server.notifications.Notification;
import org.apache.ambari.server.state.alert.AlertNotification;
import org.apache.ambari.server.state.alert.TargetType;
import org.apache.ambari.server.state.services.AlertNoticeDispatchService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.util.DefaultPDUFactory;
import com.google.inject.Singleton;
/**
* The {@link AmbariSNMPDispatcher} class is used to dispatch {@link AlertNotification} via SNMP using predefined Ambari OIDs.
*
* <pre>The base OID for Ambari is 1.3.6.1.4.1.18060.16. Off of this, we define the following:
* .0 - apacheAmbariTraps
* .1 - apacheAmbariAlerts
* From these two roots, we define other bindings:
* .1.1 - apacheAmbariAlertTable
* .1.1.1 - apacheAmbariAlertEntry
* .1.1.1.2 - alertDefinitionName
* </pre>
*/
@Singleton
public class AmbariSNMPDispatcher extends SNMPDispatcher {
private static final Logger LOG = LoggerFactory.getLogger(AmbariSNMPDispatcher.class);
public static final String BASE_AMBARI_OID = "1.3.6.1.4.1.18060.16";
public static final String APACHE_AMBARI_TRAPS_OID = BASE_AMBARI_OID + ".0";
public static final String AMBARI_ALERT_TRAP_OID = APACHE_AMBARI_TRAPS_OID + ".1";
public static final String AMBARI_ALERTS_OID = BASE_AMBARI_OID + ".1";
public static final String AMBARI_ALERT_TABLE_OID = AMBARI_ALERTS_OID + ".1";
public static final String AMBARI_ALERT_ENTRY_OID = AMBARI_ALERT_TABLE_OID + ".1";
//ALERT_ENTRY fields
public static final String AMBARI_ALERT_DEFINITION_ID_OID = AMBARI_ALERT_ENTRY_OID + ".1";
public static final String AMBARI_ALERT_DEFINITION_NAME_OID = AMBARI_ALERT_ENTRY_OID + ".2";
public static final String AMBARI_ALERT_DEFINITION_HASH_OID = AMBARI_ALERT_ENTRY_OID + ".3";
public static final String AMBARI_ALERT_NAME_OID = AMBARI_ALERT_ENTRY_OID + ".4";
public static final String AMBARI_ALERT_TEXT_OID = AMBARI_ALERT_ENTRY_OID + ".5";
public static final String AMBARI_ALERT_STATE_OID = AMBARI_ALERT_ENTRY_OID + ".6";
public static final String AMBARI_ALERT_HOST_NAME_OID = AMBARI_ALERT_ENTRY_OID + ".7";
public static final String AMBARI_ALERT_SERVICE_NAME_OID = AMBARI_ALERT_ENTRY_OID + ".8";
public static final String AMBARI_ALERT_COMPONENT_NAME_OID = AMBARI_ALERT_ENTRY_OID + ".9";
protected AmbariSNMPDispatcher(Snmp snmp) {
super(snmp);
}
public AmbariSNMPDispatcher(Integer port) throws IOException {
super(port);
}
/**
* {@inheritDoc}
*/
@Override
public String getType() {
return TargetType.AMBARI_SNMP.name();
}
/**
* {@inheritDoc}
* Uses default Ambari OIDs
*/
protected PDU prepareTrap(Notification notification, SnmpVersion snmpVersion) throws InvalidSnmpConfigurationException {
AlertNotification alertNotification;
PDU pdu = DefaultPDUFactory.createPDU(snmpVersion.getTargetVersion());
if (Notification.Type.ALERT.equals(notification.getType())) {
try {
alertNotification = (AlertNotification) notification;
} catch (ClassCastException e) {
LOG.error("Notification wasn't casted to AlertNotification. Returning empty Protocol data unit", e);
return pdu;
}
} else {
LOG.error("Notification for AmbariSNMPDispatcher should be of type AlertNotification, but it wasn't. Returning empty Protocol data unit");
return pdu;
}
pdu.setType(snmpVersion.getTrapType());
// Set trap oid for PDU
pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(AMBARI_ALERT_TRAP_OID)));
// Set notification body and subject for PDU objects with identifiers specified in dispatch properties.
AlertNoticeDispatchService.AlertInfo alertInfo = alertNotification.getAlertInfo();
addIntVariableBindingCheckForNull(pdu, AMBARI_ALERT_DEFINITION_ID_OID, new BigDecimal(alertInfo.getAlertDefinitionId()).intValueExact());
addStringVariableBindingCheckForNull(pdu, AMBARI_ALERT_DEFINITION_NAME_OID, alertInfo.getAlertDefinition().getDefinitionName());
addStringVariableBindingCheckForNull(pdu, AMBARI_ALERT_DEFINITION_HASH_OID, alertInfo.getAlertDefinitionHash());
addStringVariableBindingCheckForNull(pdu, AMBARI_ALERT_NAME_OID, alertInfo.getAlertName());
addStringVariableBindingCheckForNull(pdu, AMBARI_ALERT_TEXT_OID, alertInfo.getAlertText());
addIntVariableBindingCheckForNull(pdu, AMBARI_ALERT_STATE_OID, alertInfo.getAlertState().getIntValue());
addStringVariableBindingCheckForNull(pdu, AMBARI_ALERT_HOST_NAME_OID, alertInfo.getHostName());
addStringVariableBindingCheckForNull(pdu, AMBARI_ALERT_SERVICE_NAME_OID, alertInfo.getServiceName());
addStringVariableBindingCheckForNull(pdu, AMBARI_ALERT_COMPONENT_NAME_OID, alertInfo.getComponentName());
return pdu;
}
/**
* {@inheritDoc}
*/
@Override
protected Set<String> getSetOfDefaultNeededPropertyNames() {
return new HashSet<>(Collections.singletonList(PORT_PROPERTY));
}
/**
* Adds new {@link VariableBinding} using provided {@link OID} and value to {@link PDU}
* if val is null than adds {@link OctetString} with "null" value;
* @param pdu
* @param oid
* @param val
*/
private void addStringVariableBindingCheckForNull(PDU pdu, String oid, Object val) {
if (val == null) {
pdu.add(new VariableBinding(new OID(oid), new OctetString("null")));
} else {
pdu.add(new VariableBinding(new OID(oid),
new OctetString(String.valueOf(val))));
}
}
/**
* Adds new {@link VariableBinding} using provided {@link OID} and value to {@link PDU}
* if val is null than adds {@link OctetString} with "null" value;
* @param pdu
* @param oid
* @param val
*/
private void addIntVariableBindingCheckForNull(PDU pdu, String oid, Integer val) {
if (val == null) {
pdu.add(new VariableBinding(new OID(oid), new OctetString("null")));
} else {
pdu.add(new VariableBinding(new OID(oid),
new Integer32(val)));
}
}
}