View Javadoc

1   /*******************************************************************************
2    * Copyright (c) 2007, 2014 Massimiliano Ziccardi
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *******************************************************************************/
16  package it.jnrpe.plugin;
17  
18  import it.jnrpe.ICommandLine;
19  import it.jnrpe.Status;
20  import it.jnrpe.plugins.Metric;
21  import it.jnrpe.plugins.MetricGatheringException;
22  import it.jnrpe.plugins.PluginBase;
23  import it.jnrpe.plugins.annotations.Option;
24  import it.jnrpe.plugins.annotations.Plugin;
25  import it.jnrpe.plugins.annotations.PluginOptions;
26  import it.jnrpe.utils.BadThresholdException;
27  import it.jnrpe.utils.thresholds.ThresholdsEvaluatorBuilder;
28  
29  import java.io.IOException;
30  import java.math.BigDecimal;
31  import java.net.Inet4Address;
32  import java.net.Inet6Address;
33  import java.net.InetAddress;
34  import java.net.UnknownHostException;
35  import java.util.ArrayList;
36  import java.util.Collection;
37  import java.util.List;
38  
39  
40  /**
41   * Checks statistics for a remote host
42   * 
43   * @author Frederico Campos
44   * 
45   */
46  
47  @Plugin(name = "CHECK_PING", 
48  
49  description =
50  "Checks connection statistics for a remote host.\n\n"
51  		+ "Usage:\n\n" 
52  		+ "The example will be based upon the following command definition (ini file)\n\n" 
53  		+ "check_ssh : CHECK_PING --hostname $ARG1$ --critical $ARG2$ \n"
54  		+ "check_nrpe -H myjnrpeserver -c check_ping -a myhostname 3000,50%:\n\n"
55  		+ "THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the \n"
56  		+ "percentage of packet loss to trigger an alarm state.\n"
57  		+ "Note: a root privilege is required"		
58  	
59  		)
60  @PluginOptions({
61  	@Option(shortName = "H", longName = "hostname", description = "Hostname or ip address to ping", required = true, hasArgs = true, argName = "hostname", optionalArgs = false, option = "hostname"),
62  	@Option(shortName = "p", longName = "packets", description = "number of ICMP ECHO packets to send (Default: 5)", required = false, hasArgs = true, argName = "packets", optionalArgs = false, option = "packets"),
63  	@Option(shortName = "4", longName = "use-ipv4", description = "Use IPv4.", required = false, hasArgs = false, argName = "use-ipv4", optionalArgs = false, option = "use-ipv4"),
64  	@Option(shortName = "6", longName = "use-ipv6", description = "Use IPv6.", required = false, hasArgs = false, argName = "use-ipv6", optionalArgs = false, option = "use-ipv6"),
65  	@Option(shortName = "c", longName = "critical", description = "critical threshold pair", required = false, hasArgs = true, argName = "critical", optionalArgs = false, option = "critical"),
66  	@Option(shortName = "w", longName = "warning", description = "warning threshold pair", required = false, hasArgs = true, argName = "warning", optionalArgs = false, option = "warning"),
67  	@Option(shortName = "t", longName = "timeout", description = "Seconds before connection times out (default: 10)", required = false, hasArgs = true, argName = "timeout", optionalArgs = false, option = "timeout") })
68  public class CheckPing extends PluginBase {
69  
70  
71  	/**
72  	 * Default timeout.
73  	 */
74  	private static final int DEFAULT_TIMEOUT = 10;
75  
76  	/**
77  	 * Default packets
78  	 */
79  	private static final int DEFAULT_PACKETS = 5;
80  
81  
82  	private static final String RTA = "round trip average";
83  
84  	private static final String PACKET_LOSS = "packet loss";
85  
86  	@Override
87  	protected String getPluginName() {
88  		return "CheckPing";
89  	}
90  
91  
92  	public final void configureThresholdEvaluatorBuilder(
93  			final ThresholdsEvaluatorBuilder thrb, final ICommandLine cl)
94  					throws BadThresholdException {
95  		String critical = cl.getOptionValue("critical");
96  		String warning = cl.getOptionValue("warning");
97  
98  		String rtaCritical = getValue(0, critical);
99  		String rtaWarning = getValue(0, warning);
100 		String plCritical = getValue(1, critical);
101 		String plWarning = getValue(1, warning);
102 
103 		if (rtaCritical != null || rtaWarning != null){
104 			thrb.withLegacyThreshold(RTA, null, rtaWarning, rtaCritical);
105 		}
106 
107 		if (plCritical != null || plWarning != null){
108 			thrb.withLegacyThreshold(PACKET_LOSS, null, plWarning, plCritical);
109 		}
110 		
111 	}
112 
113 	private String getValue(int index, String str){
114 		if (str == null){
115 			return null;
116 		}
117 		String arr[] = str.split(",");
118 		if (arr.length >= index){
119 			if (arr[index].equals("")){
120 				return null;
121 			}
122 			String val =  arr[index].trim().replace("%", "");
123 			if (val.indexOf(":") < 0){
124 				val = val + ":";
125 			}
126 			return val;
127 		}
128 		return null;
129 	}
130 
131 	public Collection<Metric> gatherMetrics(ICommandLine cl) throws MetricGatheringException {
132 		List<Metric> metrics = new ArrayList<Metric>();
133 
134 		String hostname = cl.getOptionValue("hostname");
135 		int timeout = DEFAULT_TIMEOUT;
136 		if (cl.getOptionValue("timeout") != null) {
137 			timeout = Integer.parseInt(cl.getOptionValue("timeout"));
138 		}
139 		int packets = DEFAULT_PACKETS;
140 		if (cl.getOptionValue("packets") != null) {
141 			packets = Integer.parseInt(cl.getOptionValue("packets"));
142 		}
143 		
144 		double roundTripAvg = 0;
145 		int packetLossPerc = 0;
146 		long time = 0;
147 		long packetLoss = 0;
148 		for (int pings = 0; pings < packets; pings++){
149 			try {
150 				InetAddress inet = null; 
151 				if (cl.hasOption("ipv6")){
152 					inet = Inet6Address.getByName(hostname);
153 				}else if (cl.hasOption("ipv4")){
154 					inet =	Inet4Address.getByName(hostname);
155 				}else{
156 					inet =	InetAddress.getByName(hostname);
157 				}
158 				boolean reachable = false;
159 				long then = System.currentTimeMillis();
160 				reachable = inet.isReachable(timeout * 1000); 	            
161 				time += (System.currentTimeMillis() - then);
162 				if (!reachable){
163 					packetLoss++;
164 				}
165 			} catch (UnknownHostException e) {
166 				throw new MetricGatheringException(e.getMessage(), Status.CRITICAL, e);
167 			} catch(IOException e){
168 				throw new MetricGatheringException(e.getMessage(), Status.CRITICAL, e);
169 			}
170 		}
171 
172 		roundTripAvg = (double)time / packets;
173 		packetLossPerc = (int) (packetLoss/packets) * 100;
174 
175 		metrics.add(new Metric(RTA, "", new BigDecimal(roundTripAvg), null, null));
176 		metrics.add(new Metric(PACKET_LOSS, "", new BigDecimal(packetLossPerc), null, null));
177 
178 		return metrics;
179 	}
180 
181 }