You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ts...@apache.org on 2013/03/29 13:46:15 UTC
[13/25] git commit: updated refs/heads/bvt to 5727bd0
CLOUDSTACK-712: Feature Syslog Enhancements
Signed-off-by: Anshul Gangwar <an...@citrix.com>
Signed-off-by: Sateesh Chodapuneedi <sa...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/6a7156ad
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/6a7156ad
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/6a7156ad
Branch: refs/heads/bvt
Commit: 6a7156ad9af6ca173c0b685d69d5724d91d0a401
Parents: 2c176ab
Author: Anshul Gangwar <an...@citrix.com>
Authored: Wed Mar 6 14:11:47 2013 +0530
Committer: Sateesh Chodapuneedi <sa...@apache.org>
Committed: Fri Mar 29 09:53:05 2013 +0530
----------------------------------------------------------------------
client/pom.xml | 5 +
client/tomcatconf/log4j-cloud.xml.in | 15 +
plugins/alert-handlers/syslog-alerts/pom.xml | 40 ++
.../cloudstack/syslog/AlertsSyslogAppender.java | 336 +++++++++++++++
.../syslog/AlertsSyslogAppenderTest.java | 61 +++
plugins/pom.xml | 1 +
6 files changed, 458 insertions(+), 0 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6a7156ad/client/pom.xml
----------------------------------------------------------------------
diff --git a/client/pom.xml b/client/pom.xml
index 23892e1..61cda76 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -67,6 +67,11 @@
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-plugin-syslog-alerts</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-snmp-alerts</artifactId>
<version>${project.version}</version>
</dependency>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6a7156ad/client/tomcatconf/log4j-cloud.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/log4j-cloud.xml.in b/client/tomcatconf/log4j-cloud.xml.in
index ce4079f..0e7f004 100755
--- a/client/tomcatconf/log4j-cloud.xml.in
+++ b/client/tomcatconf/log4j-cloud.xml.in
@@ -74,6 +74,20 @@ under the License.
<param name="ConversionPattern" value="%-5p [%c{3}] (%t:%x) %m%n"/>
</layout>
</appender>
+
+ <!-- ============================== -->
+ <!-- Append alerts to the syslog if it is configured -->
+ <!-- ============================== -->
+
+ <appender name="ALERTSYSLOG" class="org.apache.cloudstack.syslog.AlertsSyslogAppender">
+ <param name="Threshold" value="WARN"/>
+ <param name="SyslogHosts" value=""/>
+ <param name="Facility" value="LOCAL6"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p [%c{3}] (%t:%x) %m%n"/>
+ </layout>
+ </appender>
+
<!-- ============================== -->
<!-- send alert warnings+ as the SNMP trap if it is configured! -->
<!-- ============================== -->
@@ -166,6 +180,7 @@ under the License.
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="SNMP"/>
+ <appender-ref ref="ALERTSYSLOG"/>
</logger>
<!-- ======================= -->
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6a7156ad/plugins/alert-handlers/syslog-alerts/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/alert-handlers/syslog-alerts/pom.xml b/plugins/alert-handlers/syslog-alerts/pom.xml
new file mode 100644
index 0000000..21aa54a
--- /dev/null
+++ b/plugins/alert-handlers/syslog-alerts/pom.xml
@@ -0,0 +1,40 @@
+<!--
+ ~ 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
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>cloudstack-plugins</artifactId>
+ <groupId>org.apache.cloudstack</groupId>
+ <version>4.2.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <name>Apache CloudStack Plugin - Syslog Alerts</name>
+ <artifactId>cloud-plugin-syslog-alerts</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>${cs.log4j.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6a7156ad/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java
----------------------------------------------------------------------
diff --git a/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java b/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java
new file mode 100644
index 0000000..d2f2565
--- /dev/null
+++ b/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java
@@ -0,0 +1,336 @@
+// 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.cloudstack.syslog;
+
+import com.cloud.utils.net.NetUtils;
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.net.SyslogAppender;
+import org.apache.log4j.spi.LoggingEvent;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+public class AlertsSyslogAppender extends AppenderSkeleton {
+ String _syslogHosts = null;
+ String _delimiter = ",";
+ List<String> _syslogHostsList = null;
+ List<SyslogAppender> _syslogAppenders = null;
+ private String _facility;
+ private String _pairDelimiter = "//";
+ private String _keyValueDelimiter = "::";
+ private int alertType = -1;
+ private long dataCenterId = 0;
+ private long podId = 0;
+ private long clusterId = 0;
+ private String sysMessage = null;
+ public static final int LENGTH_OF_STRING_MESSAGE_AND_KEY_VALUE_DELIMITER = 9;
+ public static final int LENGTH_OF_STRING_MESSAGE = 8;
+ public static final String MESSAGE_DELIMITER_STRING = " ";
+ //add the alertType in this array it its level needs to be set to critical
+ private static final int[] criticalAlerts = {7, 8, 9, 10, 11, 12, 13, 15, 16, 19, 20};
+ private static final Map<Integer, String> alertsMap;
+
+ static {
+ Map<Integer, String> aMap = new HashMap<Integer, String>(27);
+ aMap.put(0, "availableMemory");
+ aMap.put(1, "availableCpu");
+ aMap.put(2, "availableStorage");
+ aMap.put(3, "remainingStorageAllocated");
+ aMap.put(4, "unallocatedVirtualNetworkpublicIp");
+ aMap.put(5, "unallocatedPrivateIp");
+ aMap.put(6, "availableSecondaryStorage");
+ aMap.put(7, "host");
+ aMap.put(8, "userVmState");
+ aMap.put(9, "domainRouterVmState ");
+ aMap.put(10, "consoleProxyVmState");
+ aMap.put(11, "routingConnection");
+ aMap.put(12, "storageIssueSystemVms");
+ aMap.put(13, "usageServerStatus");
+ aMap.put(14, "managementNode");
+ aMap.put(15, "domainRouterMigrate");
+ aMap.put(16, "consoleProxyMigrate");
+ aMap.put(17, "userVmMigrate");
+ aMap.put(18, "unallocatedVlan");
+ aMap.put(19, "ssvmStopped");
+ aMap.put(20, "usageServerResult");
+ aMap.put(21, "storageDelete");
+ aMap.put(22, "updateResourceCount");
+ aMap.put(23, "usageSanityResult");
+ aMap.put(24, "unallocatedDirectAttachedPublicIp");
+ aMap.put(25, "unallocatedLocalStorage");
+ aMap.put(26, "resourceLimitExceeded");
+
+ alertsMap = Collections.unmodifiableMap(aMap);
+ }
+
+ @Override
+ protected void append(LoggingEvent event) {
+ if (!isAsSevereAsThreshold(event.getLevel())) {
+ return;
+ }
+
+ if (_syslogAppenders != null && !_syslogAppenders.isEmpty()) {
+ try {
+ String logMessage = event.getRenderedMessage();
+ if (logMessage.contains("alertType") && logMessage.contains("message")) {
+ parseMessage(logMessage);
+ String syslogMessage = createSyslogMessage();
+
+ LoggingEvent syslogEvent = new LoggingEvent(event.getFQNOfLoggerClass(), event.getLogger(),
+ event.getLevel(), syslogMessage, null);
+
+ for (SyslogAppender syslogAppender : _syslogAppenders) {
+ syslogAppender.append(syslogEvent);
+ }
+ }
+ } catch (Exception e) {
+ errorHandler.error(e.getMessage());
+ }
+ }
+ }
+
+ @Override
+ synchronized public void close() {
+ for (SyslogAppender syslogAppender : _syslogAppenders) {
+ syslogAppender.close();
+ }
+ }
+
+ @Override
+ public boolean requiresLayout() {
+ return true;
+ }
+
+ void setSyslogAppenders() {
+ if (_syslogAppenders == null) {
+ _syslogAppenders = new ArrayList<SyslogAppender>();
+ }
+
+ if (_syslogHosts == null || _syslogHosts.trim().isEmpty()) {
+ reset();
+ return;
+ }
+
+ _syslogHostsList = parseSyslogHosts(_syslogHosts);
+
+ if (!validateIpAddresses()) {
+ reset();
+ errorHandler.error(" Invalid format for the IP Addresses parameter ");
+ return;
+ }
+
+ for (String syslogHost : _syslogHostsList) {
+ _syslogAppenders.add(new SyslogAppender(getLayout(), syslogHost, SyslogAppender.getFacility(_facility)));
+ }
+ }
+
+ private List<String> parseSyslogHosts(String syslogHosts) {
+ List<String> result = new ArrayList<String>();
+
+ final StringTokenizer tokenizer = new StringTokenizer(syslogHosts, _delimiter);
+ while (tokenizer.hasMoreTokens()) {
+ result.add(tokenizer.nextToken().trim());
+ }
+ return result;
+ }
+
+ private boolean validateIpAddresses() {
+ for (String ipAddress : _syslogHostsList) {
+ if (ipAddress.trim().equalsIgnoreCase("localhost")) {
+ continue;
+ }
+ if (!NetUtils.isValidIp(ipAddress)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void parseMessage(String logMessage) {
+ final StringTokenizer messageSplitter = new StringTokenizer(logMessage, _pairDelimiter);
+ while (messageSplitter.hasMoreTokens()) {
+ final String pairToken = messageSplitter.nextToken();
+ final StringTokenizer pairSplitter = new StringTokenizer(pairToken, _keyValueDelimiter);
+ String keyToken;
+ String valueToken;
+
+ if (pairSplitter.hasMoreTokens()) {
+ keyToken = pairSplitter.nextToken().trim();
+ } else {
+ break;
+ }
+
+ if (pairSplitter.hasMoreTokens()) {
+ valueToken = pairSplitter.nextToken().trim();
+ } else {
+ break;
+ }
+
+ if (keyToken.equalsIgnoreCase("alertType") && !valueToken.equalsIgnoreCase("null")) {
+ alertType = Short.parseShort(valueToken);
+ } else if (keyToken.equalsIgnoreCase("dataCenterId") && !valueToken.equalsIgnoreCase("null")) {
+ dataCenterId = Long.parseLong(valueToken);
+ } else if (keyToken.equalsIgnoreCase("podId") && !valueToken.equalsIgnoreCase("null")) {
+ podId = Long.parseLong(valueToken);
+ } else if (keyToken.equalsIgnoreCase("clusterId") && !valueToken.equalsIgnoreCase("null")) {
+ clusterId = Long.parseLong(valueToken);
+ } else if (keyToken.equalsIgnoreCase("message") && !valueToken.equalsIgnoreCase("null")) {
+ sysMessage = getSyslogMessage(logMessage);
+ }
+ }
+ }
+
+ String createSyslogMessage() {
+ StringBuilder message = new StringBuilder();
+ message.append(severityOfAlert(alertType)).append(MESSAGE_DELIMITER_STRING);
+ InetAddress ip;
+ try {
+ ip = InetAddress.getLocalHost();
+ } catch (UnknownHostException e) {
+ ip = null;
+ }
+
+ if (ip != null) {
+ message.append(ip.getHostName()).append(MESSAGE_DELIMITER_STRING);
+ } else {
+ message.append("unknown" + MESSAGE_DELIMITER_STRING);
+ }
+
+ if (alertType > 0) {
+ message.append("alertType").append(_keyValueDelimiter).append(" ").append(alertsMap.get(alertType))
+ .append(MESSAGE_DELIMITER_STRING);
+ if (dataCenterId != 0) {
+ message.append("dataCenterId").append(_keyValueDelimiter).append(" ").append(dataCenterId)
+ .append(MESSAGE_DELIMITER_STRING);
+ }
+
+ if (podId != 0) {
+ message.append("podId").append(_keyValueDelimiter).append(" ").append(podId)
+ .append(MESSAGE_DELIMITER_STRING);
+ }
+
+ if (clusterId != 0) {
+ message.append("clusterId").append(_keyValueDelimiter).append(" ").append(clusterId)
+ .append(MESSAGE_DELIMITER_STRING);
+ }
+
+ if (sysMessage != null) {
+ message.append("message").append(_keyValueDelimiter).append(" ").append(sysMessage);
+ } else {
+ errorHandler.error(" What is the use of alert without message ");
+ }
+ } else {
+ errorHandler.error(" Invalid alert Type ");
+ }
+
+ return message.toString();
+ }
+
+ private String getSyslogMessage(String message) {
+ int lastIndexOfKeyValueDelimiter = message.lastIndexOf(_keyValueDelimiter);
+ int lastIndexOfMessageInString = message.lastIndexOf("message");
+
+ if (lastIndexOfKeyValueDelimiter - lastIndexOfMessageInString <=
+ LENGTH_OF_STRING_MESSAGE_AND_KEY_VALUE_DELIMITER) {
+ return message.substring(lastIndexOfKeyValueDelimiter + _keyValueDelimiter.length()).trim();
+ } else if (lastIndexOfMessageInString < lastIndexOfKeyValueDelimiter) {
+ return message.substring(
+ lastIndexOfMessageInString + _keyValueDelimiter.length() + LENGTH_OF_STRING_MESSAGE).trim();
+ }
+
+ return message.substring(message.lastIndexOf("message" + _keyValueDelimiter) +
+ LENGTH_OF_STRING_MESSAGE_AND_KEY_VALUE_DELIMITER).trim();
+ }
+
+ private void reset() {
+ _syslogAppenders.clear();
+ }
+
+ public void setFacility(String facility) {
+ if (facility == null) {
+ return;
+ }
+
+ this._facility = facility;
+ if (_syslogAppenders != null && !_syslogAppenders.isEmpty()) {
+ for (SyslogAppender syslogAppender : _syslogAppenders) {
+ syslogAppender.setFacility(facility);
+ }
+ }
+ }
+
+ private String severityOfAlert(int alertType) {
+ if (isCritical(alertType)) {
+ return "CRITICAL";
+ } else {
+ return "WARN";
+ }
+ }
+
+ private boolean isCritical(int alertType) {
+ for (int type : criticalAlerts) {
+ if (type == alertType) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String getFacility() {
+ return _facility;
+ }
+
+ public String getSyslogHosts() {
+ return _syslogHosts;
+ }
+
+ public void setSyslogHosts(String syslogHosts) {
+ this._syslogHosts = syslogHosts;
+ this.setSyslogAppenders();
+ }
+
+ public String getDelimiter() {
+ return _delimiter;
+ }
+
+ public void setDelimiter(String delimiter) {
+ this._delimiter = delimiter;
+ }
+
+ public String getPairDelimiter() {
+ return _pairDelimiter;
+ }
+
+ public void setPairDelimiter(String pairDelimiter) {
+ this._pairDelimiter = pairDelimiter;
+ }
+
+ public String getKeyValueDelimiter() {
+ return _keyValueDelimiter;
+ }
+
+ public void setKeyValueDelimiter(String keyValueDelimiter) {
+ this._keyValueDelimiter = keyValueDelimiter;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6a7156ad/plugins/alert-handlers/syslog-alerts/test/org/apache/cloudstack/syslog/AlertsSyslogAppenderTest.java
----------------------------------------------------------------------
diff --git a/plugins/alert-handlers/syslog-alerts/test/org/apache/cloudstack/syslog/AlertsSyslogAppenderTest.java b/plugins/alert-handlers/syslog-alerts/test/org/apache/cloudstack/syslog/AlertsSyslogAppenderTest.java
new file mode 100644
index 0000000..68585ee
--- /dev/null
+++ b/plugins/alert-handlers/syslog-alerts/test/org/apache/cloudstack/syslog/AlertsSyslogAppenderTest.java
@@ -0,0 +1,61 @@
+// 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.cloudstack.syslog;
+
+import org.apache.log4j.PatternLayout;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.naming.ConfigurationException;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+public class AlertsSyslogAppenderTest {
+ AlertsSyslogAppender _appender = new AlertsSyslogAppender();
+
+ @Before
+ public void setUp() throws ConfigurationException {
+ _appender.setLayout(new PatternLayout("%-5p [%c{3}] (%t:%x) %m%n"));
+ _appender.setFacility("LOCAL6");
+ }
+
+ @Test
+ public void setSyslogAppendersTest() {
+ _appender.setSyslogHosts("10.1.1.1,10.1.1.2");
+ assertEquals(" error Syslog Appenders list size not as expected ", 2, _appender._syslogAppenders.size());
+ }
+
+ @Test
+ public void setSyslogAppendersNegativeTest() {
+ //setting invalid IP for Syslog Hosts
+ _appender.setSyslogHosts("10.1.1.");
+ assertTrue(" list was expected to be empty", _appender._syslogAppenders.isEmpty());
+ }
+
+ @Test
+ public void appendTest() {
+ String message = "alertType:: 14 // dataCenterId:: 0 // podId:: 0 // clusterId:: null // message:: Management" +
+ " server node 127.0.0.1 is up";
+ _appender.parseMessage(message);
+ String createdMessage = _appender.createSyslogMessage();
+ assertTrue(" message is not as expected ", createdMessage.contains("alertType:: managementNode" +
+ AlertsSyslogAppender.MESSAGE_DELIMITER_STRING + "message:: Management server node 127.0.0.1 is up"));
+ assertTrue("severity level not as expected ", createdMessage.contains("WARN"));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6a7156ad/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 39d9907..d7e8deb 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -59,6 +59,7 @@
<module>storage/volume/solidfire</module>
<module>storage/volume/default</module>
<module>alert-handlers/snmp-alerts</module>
+ <module>alert-handlers/syslog-alerts</module>
</modules>
<dependencies>