Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CF5C5FE78 for ; Sat, 30 Mar 2013 09:58:41 +0000 (UTC) Received: (qmail 65391 invoked by uid 500); 30 Mar 2013 09:58:39 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 64207 invoked by uid 500); 30 Mar 2013 09:58:36 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 62501 invoked by uid 99); 30 Mar 2013 09:58:32 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 30 Mar 2013 09:58:32 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 63DFA83457B; Sat, 30 Mar 2013 09:58:31 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: widodh@apache.org To: commits@cloudstack.apache.org Date: Sat, 30 Mar 2013 09:58:52 -0000 Message-Id: <9a2d082e71ee4d16b38ca8911617877f@git.apache.org> In-Reply-To: <4247a17f41bc48deb8f48309d3d6aadf@git.apache.org> References: <4247a17f41bc48deb8f48309d3d6aadf@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [23/52] [abbrv] git commit: updated refs/heads/qemu-img to 44197a0 CLOUDSTACK-712: Feature Syslog Enhancements Signed-off-by: Anshul Gangwar Signed-off-by: Sateesh Chodapuneedi 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/qemu-img Commit: 6a7156ad9af6ca173c0b685d69d5724d91d0a401 Parents: 2c176ab Author: Anshul Gangwar Authored: Wed Mar 6 14:11:47 2013 +0530 Committer: Sateesh Chodapuneedi 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 @@ org.apache.cloudstack + cloud-plugin-syslog-alerts + ${project.version} + + + org.apache.cloudstack cloud-plugin-snmp-alerts ${project.version} 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. + + + + + + + + + + + + + + @@ -166,6 +180,7 @@ under the License. + 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 @@ + + + + cloudstack-plugins + org.apache.cloudstack + 4.2.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + Apache CloudStack Plugin - Syslog Alerts + cloud-plugin-syslog-alerts + + + + log4j + log4j + ${cs.log4j.version} + + + + \ 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 _syslogHostsList = null; + List _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 alertsMap; + + static { + Map aMap = new HashMap(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(); + } + + 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 parseSyslogHosts(String syslogHosts) { + List result = new ArrayList(); + + 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 @@ storage/volume/solidfire storage/volume/default alert-handlers/snmp-alerts + alert-handlers/syslog-alerts