Add missing license headers
[netvirt.git] / vpnservice / bgpmanager / bgpmanager-impl / src / main / java / org / opendaylight / netvirt / bgpmanager / oam / BgpCounters.java
1 /*
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.bgpmanager.oam;
10
11 import javax.management.JMException;
12 import javax.management.MBeanServer;
13 import javax.management.ObjectName;
14 import java.io.*;
15 import java.lang.management.ManagementFactory;
16 import java.net.*;
17 import java.util.*;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23
24 /**
25  * Created by ECHIAPT on 8/4/2015.
26  */
27 public class BgpCounters extends TimerTask {
28
29     private static final Logger LOGGER = LoggerFactory.getLogger(BgpCounters.class);
30     public static BgpCountersBroadcaster bgpStatsBroadcaster = null;
31     public MBeanServer bgpStatsServer = null;
32     public  Map <String, String> countersMap = new HashMap<String, String>();
33
34     @Override
35     public void run () {
36         try {
37             if (LOGGER.isDebugEnabled()) {
38                 LOGGER.debug("Fetching counters from BGP at " + new Date());
39             }
40             resetCounters();
41             fetchCmdOutputs("cmd_ip_bgp_summary.txt","show ip bgp summary");
42             fetchCmdOutputs("cmd_bgp_ipv4_unicast_statistics.txt", "show bgp ipv4 unicast statistics");
43             fetchCmdOutputs("cmd_ip_bgp_vpnv4_all.txt", "show ip bgp vpnv4 all");
44             parse_ip_bgp_summary();
45             parse_bgp_ipv4_unicast_statistics();
46             parse_ip_bgp_vpnv4_all();
47             if (LOGGER.isDebugEnabled()) {
48                 dumpCounters();
49             }
50             if (bgpStatsBroadcaster == null) {
51                 //First time execution
52                 try {
53                     bgpStatsBroadcaster = new BgpCountersBroadcaster();
54                     bgpStatsServer = ManagementFactory.getPlatformMBeanServer();
55                     ObjectName bgpStatsObj = new ObjectName("SDNC.PM:type=BgpCountersBroadcaster");
56                     bgpStatsServer.registerMBean(bgpStatsBroadcaster, bgpStatsObj);
57                     LOGGER.info("BGP Counters MBean Registered :::");
58                 } catch (JMException e) {
59                     LOGGER.error("Adding a NotificationBroadcaster failed." , e);
60                     return;
61                 }
62             }
63             bgpStatsBroadcaster.setBgpCountersMap(countersMap);
64             if (LOGGER.isDebugEnabled()) {
65                 LOGGER.debug("Finished updating the counters from BGP at " + new Date());
66             }
67         } catch (Exception e) {
68             LOGGER.error("Failed to publish bgp counters ", e);
69         }
70     }
71
72     public void dumpCounters () {
73         Iterator<Map.Entry<String, String>> entries = countersMap.entrySet().iterator();
74         while (entries.hasNext()) {
75             Map.Entry<String, String> entry = entries.next();
76             LOGGER.debug(entry.getKey() + ", Value = " + entry.getValue());
77         }
78     }
79
80     public static void fetchCmdOutputs (String filename, String cmdName) throws  IOException  {
81         Socket socket;
82         int serverPort = 2605;
83         String serverName = BgpConstants.DEFAULT_BGP_HOST_NAME;
84         int sockTimeout = 2;
85         PrintWriter out_to_socket;
86         BufferedReader in_from_socket;
87         char cbuf[] = new char[10];
88         char op_buf[];
89         StringBuilder sb = new StringBuilder();
90         int ip, ret;
91         StringBuilder temp;
92         char ch, gt = '>', hash = '#';
93         String vtyPassword = BgpConstants.QBGP_VTY_PASSWORD;
94         String passwordCheckStr = "Password:";
95         String enableString = "en";
96         String prompt, replacedStr;
97
98         try
99         {
100             socket = new Socket(serverName, serverPort);
101
102         }
103         catch (UnknownHostException ioe) {
104             LOGGER.error("No host exists: " + ioe.getMessage());
105             return;
106         }
107         catch (IOException ioe) {
108             LOGGER.error("I/O error occured " + ioe.getMessage());
109             return;
110         }
111         try {
112             socket.setSoTimeout(sockTimeout*1000);
113             out_to_socket = new PrintWriter(socket.getOutputStream(), true);
114             in_from_socket = new BufferedReader(new InputStreamReader(socket.getInputStream()));
115
116         } catch (IOException ioe) {
117             LOGGER.error("IOException thrown.");
118             socket.close();
119             return;
120         }
121         while (true) {
122             try {
123                 ret = in_from_socket.read(cbuf);
124             }
125             catch (SocketTimeoutException ste) {
126                 LOGGER.error("Read from Socket timed Out while asking for password.");
127                 socket.close();
128                 return;
129             }
130             catch (IOException ioe) {
131                 LOGGER.error("Caught IOException");
132                 socket.close();
133                 return;
134             }
135             if (ret == -1) {
136                 LOGGER.error("Connection closed by BGPd.");
137                 socket.close();
138                 return;
139             } else {
140                 sb.append(cbuf);
141                 if (sb.toString().contains(passwordCheckStr)) {
142                     break;
143                 }
144             }
145         }
146
147         sb.setLength(0);
148         out_to_socket.println(vtyPassword);
149
150         while (true) {
151             try {
152                 ip = in_from_socket.read();
153             }
154             catch (SocketTimeoutException ste) {
155                 LOGGER.error(sb.toString());
156                 LOGGER.error("Read from Socket timed Out while verifying the password.");
157                 socket.close();
158                 return;
159             }
160             if (ip == (int)gt) {
161                 break;
162             } else if (ip == -1) {
163                 LOGGER.error(sb.toString());
164                 LOGGER.error("Connection closed by BGPd.");
165                 socket.close();
166                 return;
167             } else {
168                 ch = (char)ip;
169                 sb.append(ch);
170
171             }
172         }
173
174         prompt = sb.toString();
175         prompt = prompt.trim();
176         sb.setLength(0);
177         out_to_socket.println(enableString);
178
179         while (true) {
180             try {
181                 ip = in_from_socket.read();
182             }
183             catch (SocketTimeoutException ste) {
184                 LOGGER.error(sb.toString());
185                 LOGGER.error("Read from Socket timed Out while keying the en keyword.");
186                 socket.close();
187                 return;
188             }
189             if (ip == (int)hash) {
190                 break;
191             } else if (ip == -1) {
192                 LOGGER.error(sb.toString());
193                 LOGGER.error("Connection closed by BGPd.");
194                 socket.close();
195                 return;
196             } else {
197                 ch = (char)ip;
198                 sb.append(ch);
199
200             }
201         }
202         sb.setLength(0);
203         temp = new StringBuilder();
204         File file;
205         FileWriter fileWritter;
206         BufferedWriter bufferWritter;
207
208         try {
209             file = new File(filename);
210             if (!file.exists()) {
211                 file.createNewFile();
212             }
213             fileWritter = new FileWriter(file.getName(), true);
214             bufferWritter = new BufferedWriter(fileWritter);
215         } catch (IOException e) {
216             return;
217         }
218         out_to_socket.println(cmdName);
219         temp.setLength(0);
220         while (true) {
221             try {
222                 op_buf = new char[100];
223                 ret = in_from_socket.read(op_buf);
224
225             } catch (SocketTimeoutException ste) {
226                 break;
227             } catch (SocketException soc) {
228                 break;
229             } catch (IOException ioe) {
230                 ioe.printStackTrace();
231                 break;
232             }
233
234             if (ret == -1) {
235                 break;
236             }
237             temp.append(op_buf);
238         }
239         String outputStr = temp.toString();
240         StringBuffer output = new StringBuffer();
241
242         outputStr.replaceAll("^\\s+|\\s+$", "");
243         output.append(outputStr);
244         if (output.toString().trim().contains(prompt)) {
245             int index = output.toString().lastIndexOf(prompt);
246             String newString = output.toString().substring(0, index);
247             output.setLength(0);
248             output.append(newString);
249         }
250         try {
251             bufferWritter.write(output.toString().trim());
252             temp.setLength(0);
253         } catch (IOException e) {
254             e.printStackTrace();
255             return;
256         }
257         try {
258             bufferWritter.close();
259             fileWritter.close();
260             socket.close();
261
262         } catch (IOException e) {
263             e.printStackTrace();
264             return;
265         }
266     }
267
268     public boolean validate(final String ip){
269         if (ip == null || ip.equals("")) {
270             return false;
271         }
272         final String PATTERN =
273                 "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
274         Pattern pattern = Pattern.compile(PATTERN);
275         Matcher matcher = pattern.matcher(ip);
276         return matcher.matches();
277     }
278
279
280     /*
281      * The below function parses the output of "show ip bgp summary" saved in a file.
282      * Below is the snippet for the same :-
283         <output>
284         BGP router identifier 10.183.254.53, local AS number 101
285         .....
286         Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
287         10.183.254.76   4   100       3       4        0    0    0 00:01:27        0
288         .........
289         Total number of neighbors 1
290         </output>
291      */
292
293     public void parse_ip_bgp_summary() {
294         File file = new File("cmd_ip_bgp_summary.txt");
295         Scanner scanner;
296         String lineFromFile;
297         List<String> inputStrs = new ArrayList<String>();
298         int i = 0;
299         String as,rx, tx;
300         boolean startEntries = false;
301         String[] result;
302         String StrIP;
303
304         try {
305             scanner = new Scanner(file);
306         } catch (IOException e) {
307             LOGGER.error("Could not process the file " + file.getAbsolutePath());
308             return ;
309         }
310         while (scanner.hasNextLine()) {
311
312             lineFromFile = scanner.nextLine();
313             inputStrs.add(lineFromFile);
314         }
315         String str;
316         StringBuilder NbrInfoKey = new StringBuilder();
317
318         while (i < inputStrs.size()) {
319             str = inputStrs.get(i);
320             if (str.contains("State/PfxRcd")) {
321                 startEntries = true;
322             } else if (startEntries == true) {
323                 result = str.split("\\s+");
324                try {
325                     StrIP = result[0].trim();
326                     if (!validate(StrIP)) {
327                         return;
328                     }
329                     as = result[2];
330                     rx = result[3];
331                     tx = result[4];
332
333                     NbrInfoKey.setLength(0);
334                     NbrInfoKey.append(BgpConstants.BGP_COUNTER_NBR_PKTS_RX).append(":").
335                            append("BGP_Nbr_IP_").append(StrIP).append("_AS_").append(as).append("_PktsReceived");
336                     countersMap.put(NbrInfoKey.toString(), rx);
337
338
339                     NbrInfoKey.setLength(0);
340                     NbrInfoKey.append(BgpConstants.BGP_COUNTER_NBR_PKTS_TX).append(":").
341                            append("BGP_Nbr_IP_").append(StrIP).append("_AS_").append(as).append("_PktsSent");
342                     countersMap.put(NbrInfoKey.toString(), tx);
343                 } catch (Exception e) {
344                     return;
345                 }
346             }
347             i++;
348         }
349  }
350     /*
351      * The below function parses the output of "show bgp ipv4 unicast statistics" saved in a file.
352      * Below is the sample output for the same :-
353         <output>
354         BGP IPv4 Unicast RIB statistics
355         ...
356         Total Prefixes                :            8
357         ......
358         </output>
359      */
360
361     public void parse_bgp_ipv4_unicast_statistics() {
362        File file = new File("cmd_bgp_ipv4_unicast_statistics.txt");
363        Scanner scanner;
364        String lineFromFile;
365        StringBuilder key = new StringBuilder();
366        String totPfx = "";
367        List<String> inputStrs = new ArrayList<String>();
368        try {
369            scanner = new Scanner(file);
370        } catch (IOException e) {
371            System.err.println("Could not process the file " + file.getAbsolutePath());
372            return ;
373        }
374        while (scanner.hasNextLine()) {
375
376            lineFromFile = scanner.nextLine();
377            inputStrs.add(lineFromFile);
378        }
379
380        int i = 0;
381        String instr;
382        while (i < inputStrs.size()) {
383            instr = inputStrs.get(i);
384            if (instr.contains("Total Prefixes")) {
385                String[] result = instr.split(":");
386                try {
387                    totPfx = result[1].trim();
388                } catch (Exception e) {
389                    totPfx = "0";
390                }
391                break;
392            }
393            i++;
394        }
395         key.setLength(0);
396         key.append(BgpConstants.BGP_COUNTER_TOTAL_PFX).append(":").
397                 append("Bgp_Total_Prefixes");
398         countersMap.put(key.toString(), totPfx);
399     }
400
401     /*
402      *  The below function parses the output of "show ip bgp vpnv4 all" saved in a file.
403      *  Below is the sample output for the same :-
404      *  show ip bgp vpnv4 all
405         <output>
406         BGP table version is 0, local router ID is 10.183.181.21
407         ......
408         Route Distinguisher: 100:1
409         *>i15.15.15.15/32   10.183.181.25            0    100      0 ?
410         *>i17.18.17.17/32   10.183.181.25            0    100      0 ?
411         *>i17.18.17.17/32   10.183.181.25            0    100      0 ?
412         *>i17.18.17.17/32   10.183.181.25            0    100      0 ?
413         Route Distinguisher: 100:2
414         *>i16.16.16.16/32   10.183.181.25            0    100      0 ?
415         *>i18.18.18.18/32   10.183.181.25            0    100      0 ?
416         *>i17.18.17.17/32   10.183.181.25            0    100      0 ?
417         </output>
418      */
419     public void parse_ip_bgp_vpnv4_all() {
420         File file = new File("cmd_ip_bgp_vpnv4_all.txt");
421         Scanner scanner;
422         String lineFromFile;
423         List<String> inputStrs = new ArrayList<String>();
424
425         try {
426             scanner = new Scanner(file);
427         } catch (IOException e) {
428             System.err.println("Could not process the file " + file.getAbsolutePath());
429             return ;
430         }
431         while (scanner.hasNextLine()) {
432             lineFromFile = scanner.nextLine();
433             inputStrs.add(lineFromFile);
434         }
435         int i = 0;
436         String instr, rd;
437         while (i < inputStrs.size()) {
438             instr = inputStrs.get(i);
439             if (instr.contains("Route Distinguisher")) {
440                 String[] result = instr.split(":");
441                 rd = result[1].trim() + "_" + result[2].trim();
442                 i = processRouteCount(rd, i + 1,  inputStrs);
443
444             }
445             i++;
446         }
447
448     }
449
450     public int processRouteCount(String rd, int startIndex, List<String> inputStrs) {
451         int num = startIndex, route_count = 0;
452         String str;
453         StringBuilder key = new StringBuilder();
454         str = inputStrs.get(num);
455
456         while (str != null && !str.trim().equals("") &&
457                 num <inputStrs.size()) {
458             if (str.contains("Route Distinguisher")) {
459                 key.setLength(0);
460                 key.append(BgpConstants.BGP_COUNTER_RD_ROUTE_COUNT).append(":").
461                         append("BGP_RD_").append(rd).append("_route_count");
462                 countersMap.put(key.toString(), Integer.toString(route_count));
463                 return num - 1;
464             }
465             route_count++;
466             num++;
467             if (num == inputStrs.size()) {
468                 break;
469             }
470             str = inputStrs.get(num);
471         }
472         if (route_count == 0) {
473             // Erroneous condition, should never happen.
474             // Implies that the file contains marker for RD  without routes.
475             // will form an infinite loop if not broken
476             // by sending a big number back.
477             return ~0;
478         }
479         key.setLength(0);
480         key.append(BgpConstants.BGP_COUNTER_RD_ROUTE_COUNT).append(":").
481                 append("BGP_RD_").append(rd).append("_route_count");
482         countersMap.put(key.toString(), Integer.toString(route_count));
483         return num - 1;
484     }
485
486     public void resetCounters() {
487         countersMap.clear();
488         resetFile("cmd_ip_bgp_summary.txt");
489         resetFile("cmd_bgp_ipv4_unicast_statistics.txt");
490         resetFile("cmd_ip_bgp_vpnv4_all.txt");
491     }
492
493     public void resetFile(String fileName) {
494         File fileHndl = (new File(fileName));
495         PrintWriter writer;
496         boolean success;
497
498         success = fileHndl.delete();
499         if (!success) {
500             try {
501                 writer = new PrintWriter(fileHndl);
502                 writer.print("");
503                 writer.close();
504             } catch (Exception e) {
505                 return;
506             }
507         }
508
509     }
510
511 }