h_avc.py revision 8b52a31e
1#!/router/bin/python-2.4.3
2import time,os, sys, string
3from os.path import exists
4from os import system, remove, chdir
5import re
6import time
7import random
8import copy
9import telnetlib
10import datetime
11import collections
12from trex_perf import TrexRunException
13
14
15import random
16import time
17
18class RouterIOException(Exception):
19    def __init__ (self, reason):
20        # generate the error message
21        #self.message = "\nSummary of error:\n\n %s\n" % (reason)
22        self.message = reason
23
24    def __str__(self):
25        return self.message
26
27# basic router class
28class Router:
29    def __init__ (self, host, port, password, str_wait = "#"):
30        self.host = host
31        self.port = port;
32        self.pr = str_wait;
33        self.password = password
34        self.to = 60
35        self.cpu_util_histo = []
36
37    # private function - command send
38    def _command (self, command, match = None, timeout = None):
39        to = timeout if (timeout != None) else self.to
40        m = match if (match != None) else [self.pr]
41
42        if not isinstance(m, list):
43            m = [m]
44
45        total_to = 0
46        while True:
47            self.tn.write(command + "\n")
48            ret = self.tn.expect(m, timeout = 2)
49            total_to += 2
50
51            if ret[0] != -1:
52                result = {}
53                result['match_index'] = ret[0]
54                result['output'] = ret[2]
55                return (result)
56
57            if total_to >= self.to:
58                raise RouterIOException("Failed to process command to router %s" % command)
59
60    # connect to router by telnet
61    def connect (self):
62        # create telnet session
63        self.tn = telnetlib.Telnet ()
64
65        try:
66            self.tn.open(self.host, self.port)
67        except IOError:
68            raise RouterIOException("Failed To Connect To Router interface at '%s' : '%s'" % (self.host, self.port))
69
70        # get a ready console and decides if you need password
71        ret = self._command("", ["Password", ">", "#"])
72        if ret['match_index'] == 0:
73            self._command(self.password, [">", "#"])
74
75        # can't hurt to call enable even if on enable
76        ret = self._command("enable 15", ["Password", "#"])
77        if (ret['match_index'] == 0):
78            self._command(self.password, "#")
79
80        self._command("terminal length 0")
81
82    def close (self):
83        self.tn.close ()
84        self.tn = None
85
86    # implemented through derived classes
87    def sample_cpu (self):
88        raise Exception("abstract method called")
89
90    def get_last_cpu_util (self):
91        if not self.cpu_util_histo:
92            return (0)
93        else:
94            return self.cpu_util_histo[len(self.cpu_util_histo) - 1]
95
96    def get_cpu_util_histo (self):
97        return self.cpu_util_histo
98
99    def get_filtered_cpu_util_histo (self):
100        trim_start = int(0.15 * len(self.cpu_util_histo))
101
102        filtered = self.cpu_util_histo[trim_start:]
103        if not filtered:
104            return [0]
105
106        m = collections.Counter(filtered).most_common(n = 1)[0][0]
107        #m = max(self.cpu_util_histo)
108        filtered = [x for x in filtered if (x > (0.9*m))]
109        return filtered
110
111    def clear_sampling_stats (self):
112        self.cpu_util_histo = []
113
114
115    # add a sample to the database
116    def sample_stats (self):
117        # sample CPU util
118        cpu_util = self.sample_cpu()
119        self.cpu_util_histo.append(cpu_util)
120
121    def get_stats (self):
122        stats = {}
123
124        filtered_cpu_util = self.get_filtered_cpu_util_histo()
125
126        if not filtered_cpu_util:
127            stats['cpu_util'] = 0
128        else:
129            stats['cpu_util'] = sum(filtered_cpu_util)/len(filtered_cpu_util)
130
131        stats['cpu_histo'] = self.get_cpu_util_histo()
132
133        return stats
134
135
136class ASR1k(Router):
137    def __init__ (self, host, password, port, str_wait = "#"):
138        Router.__init__(self, host, password, port, str_wait)
139
140    def sample_cpu (self):
141        cpu_show_cmd = "show platform hardware qfp active datapath utilization | inc Load"
142        output = self._command(cpu_show_cmd)['output']
143        lines = output.split('\n');
144
145        cpu_util = -1.0
146        # search for the line
147        for l in lines:
148            m = re.match("\W*Processing: Load\D*(\d+)\D*(\d+)\D*(\d+)\D*(\d+)\D*", l)
149            if m:
150                cpu_util = float(m.group(1))
151
152        if (cpu_util == -1.0):
153            raise Exception("cannot determine CPU util. for asr1k")
154
155        return cpu_util
156
157
158class ISR(Router):
159    def __init__ (self, host, password, port, str_wait = "#"):
160        Router.__init__(self, host, password, port, str_wait)
161
162    def sample_cpu (self):
163        cpu_show_cmd = "show processes cpu sorted | inc CPU utilization"
164        output = self._command(cpu_show_cmd)['output']
165        lines = output.split('\n');
166
167        cpu_util = -1.0
168
169        # search for the line
170        for l in lines:
171            m = re.match("\W*CPU utilization for five seconds: (\d+)%/(\d+)%", l)
172            if m:
173                max_cpu_util = float(m.group(1))
174                min_cpu_util = float(m.group(2))
175                cpu_util = (min_cpu_util + max_cpu_util)/2
176
177        if (cpu_util == -1.0):
178            raise Exception("cannot determine CPU util. for ISR")
179
180        return cpu_util
181
182
183
184if __name__ == "__main__":
185    #router = ASR1k("pqemb19ts", "cisco", port=2052)
186    router = ISR("10.56.198.7", "lab")
187    router.connect()
188    for i in range(1, 10):
189        router.sample_stats()
190        time.sleep(1)
191
192
193
194
195
196