Statistics
| Branch: | Tag: | Revision:

root / iooclient / eos_pmd.py @ dfb0ec90

History | View | Annotate | Download (13.8 kB)

1
# Copyright 2012 Leonidas Poulopoulos
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#    http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

    
15
from eos import eos
16
import sys
17
from pyparsing import *
18

    
19
class eosPmd(eos):
20
    '''
21
    Subclass of eos to connect to the PM subsystem
22
    '''
23
    
24
    def __init__(self, server=None, port=None, password=None):
25
        '''
26
        
27
        Constructor for the class.
28

29
        @type server: String
30
        @param server: The Hostname or IPv4 address of the Alcatel NMS.
31
        
32
        @type port: Integer
33
        @param port: The TCP port on the Alcatel NMS we will connect to. Default 20007
34
        
35
        @type password: String
36
        @param password: The password for this connection.
37
        
38
        @rtype: Handler
39
        @return: A connection handler of this class.
40
        '''
41
        if port == None:
42
            port = 20007
43
        return eos.__init__(self, server, port, password)
44
    
45
    def list_pm_data(self, startPeriod=None, endPeriod=None, neNames=[], periodType=None, counters=[], pmPoints=[], parse=True):
46
        '''
47
        Function used to obtain a listing of of PM DATA from NMS. Depending on parse value the output is either raw data from NMS 
48
        or structured python data
49
        
50
        Usage:
51
        
52
            >>> from iooclient.eos_pmd import * 
53
            >>> pmd = eosPmd('1.2.3.4', 20007, 'password')
54
            >>> pmd.list_pm_data()
55
            [{'{'friendlyName': 'elementName',
56
              'neLocationName': Athens,
57
              'notificationType': 'pmPointList',
58
              ...
59
        
60
        or:
61
        
62
            >>> from iooclient.eos_pmd import * 
63
            >>> with eosPmd('1.2.3.4', 20007, 'password') as pmd:
64
            >>>    pmd.list_pm_data()
65
            [{'{'friendlyName': 'elementName',
66
              'neLocationName': Athens,
67
              'notificationType': 'pmPointList',
68
              ... 
69
        
70
        @type startPeriod: String
71
        @param startPeriod: From when to collect PM data. Format: YYYYMMDDQH where QH in [00,96] representing 15min periods in a day.
72
        
73
        @type endPeriod: String
74
        @param endPeriod: To when to collect PM data. Format: YYYYMMDDQH where QH in [00,96] representing 15min periods in a day.
75
        
76
        @type neNames: A list of strings
77
        @param neNames: A list of NetworkElement names with pmPoints assigned. If omitted all NEs are assumed. To get different pmpoints from different network elements use the notation ['neName1{pmpoint1|pmpoint2}','neName2{pmpoint4|pmpoint5}','neName3']
78
                
79
        @type periodType: String
80
        @param periodType: The period of monitoring. Values: 15, 1h, 24, RM1, RM2, RM3, RM4, RM5, FL, immediate, peak, 30-day, IM, day, month. Default 15
81
        
82
        @type counters: A list of strings
83
        @param counters: The counters for the above NetworkElements to fetch. Assumes that the Network Elements have the same pmPoints. If omitted all counters are returned
84
        
85
        @type pmPoints: A list of strings
86
        @param pmPoints: The pmPoints for the above NetworkElements to fetch. Assumes that the Network Elements have the same pmPoints. If omitted all pmPoints are fetched.
87
        
88
        @type parse: Boolean
89
        @param parse: Default: True. If set to True, the output is a python list of dictionaries. Otherwise the output is the NMS response text.   
90
        
91
        @rtype: String or list of dictionaries
92
        @return: Performance monitoring data (counter values) in raw text format or in structured format. False in case of errors.
93
        '''
94
        extras = []
95
        extras.append('periodType=%s'%(periodType) if periodType else 'periodType=15')
96
        extras.append('startPeriod=%s'%(startPeriod) if startPeriod else '')
97
        extras.append('endPeriod=%s'%(endPeriod) if endPeriod else '')
98
        extras.append('counters={%s}'%(('|'.join(counters)) if counters else ''))
99
        pmpoints = '{%s}' %('|'.join(["pmPoint="+pmPoint for pmPoint in pmPoints])) if pmPoints else None
100
        extras.append('neName=%s'%(''.join([name+(pmpoints or '{}') for name in neNames])) if neNames else '')
101
        params = "|".join(extras) or ''
102
        message = "LIST_PM_DATA_REQ[%s]" %params
103
        if self.send(message) == False:
104
            return False
105
        reply_header = self.get_part()
106
        if reply_header != "LIST_PM_DATA_CONF[]" :
107
            print "Error: Asked for %s but got unexpected output: %s\n" %(message, reply_header)
108
            return False
109
        reply = self.get()
110
        if reply == "DATA_END_NOTIF[]":
111
            return False
112
        if parse:
113
            ret = self.parsePmData(reply)
114
        else:
115
            ret = reply
116
        return ret
117
    
118
    
119
    def list_pm_point(self, neNames=[], periodType=None, period=None, parse=True, listAll=False):
120
        '''
121
        Function used to obtain a listing of of PM points from NMS. Depending on parse value the output is either raw data from NMS 
122
        or structured python data 
123
        
124
        Usage:
125
            
126
            >>> from iooclient.eos_pmd import * 
127
            >>> pmd = eosPmd('1.2.3.4', 20007, 'password')
128
            >>> pmd.list_pm_point()
129
            [{'{'friendlyName': 'elementName',
130
              'neLocationName': Athens,
131
              'notificationType': 'pmPointList',
132
              ...
133
            
134
        or:
135
            
136
            >>> from iooclient.eos_pmd import * 
137
            >>> with eosPmd('1.2.3.4', 20007, 'password') as pmd:
138
            >>>    pmd.list_pm_point()
139
            [{'{'friendlyName': 'elementName',
140
              'neLocationName': Athens,
141
              'notificationType': 'pmPointList',
142
            ...
143
        
144
        @type neNames: A list of strings
145
        @param neNames: A list of NetworkElement names with pmPoints assigned. If omitted, all NEs are assumed
146
                
147
        @type periodType: String
148
        @param periodType: The period of monitoring. Values: 15, 1h, 24, RM1, RM2, RM3, RM4, RM5, FL, immediate, peak, 30-day, IM, day, month. Default 15
149
               
150
        @type period: String
151
        @param period: Period during which pm points were collected. Format: YYYYMMDDQH where QH in [00,96] representing 15min periods in a day.
152
        
153
        @type parse: Boolean
154
        @param parse: Default: True. If set to True, the output is a python list of dictionaries. Otherwise the output is the NMS response text.
155
        
156
        @type listAll: Boolean
157
        @param listAll: Default: False. If set to True, the output will be all points regardless of the default period set. Else, only the default period data will be fetched
158
        
159
        @rtype: String or list of dictionaries
160
        @return: Performance monitoring points (counter names) in raw text or in structured format. False in case of errors.
161
        '''
162
        extras = []
163
        extras.append('%s'%(periodType) if periodType else '15')
164
        extras.append('%s'%(period) if period else '')
165
        extras.append('{%s}'%(('|'.join(neNames)) if neNames else ''))
166
        params = "|".join(extras) or ''
167
        if listAll:
168
            params=''
169
        message = "LIST_PM_POINT_REQ[%s]" %params
170
        if self.send(message) == False:
171
            return False
172
        reply_header = self.get_part()
173
        if reply_header != "LIST_PM_POINT_CONF[]" :
174
            print "Error: Asked for %s but got unexpected output: %s\n" %(message, reply_header)
175
            return False
176
        reply = self.get()
177
        if reply == "DATA_END_NOTIF[]":
178
            return False
179
        if parse:
180
            ret = self.parsePmPoint(reply)
181
        else:
182
            ret = reply
183
        return ret
184
        
185
    def setGroupCounters(self, l, s, toks):
186
        ''' 
187
        Pyparsing action parser to include counters as key in pmPoint parsing
188
        '''
189
        return [["counters", toks[0][0].asList()]]
190
    
191
    def setGroupPmpoints(self, l, s, toks):
192
        ''' 
193
        Pyparsing action parser to include pmpoints as key in pmPoint parsing
194
        '''
195
        return [["pmpoints", toks[0][0].asList()]]
196
    
197
    def setGroupPeriods(self, l, s, toks):
198
        ''' 
199
        Pyparsing action parser to include periods as key in pmPoint parsing
200
        '''
201
        return [["periods", toks[0][0].asList()]]
202
    
203
    def parsePmPoint(self, data):
204
        ''' 
205
        Pyparsing pmpoint parser
206
        
207
        @type data: String
208
        @param data: Raw output from the NMS.
209
        
210
        @rtype: list of dicts
211
        @return: Transforms the NMS string into python list of dictionaries using the NMS delimiters
212
        '''
213
        escapechar = "\\"
214
        wordtext = CharsNotIn('\\*?^:"[]|={}')
215
        escape = Suppress(escapechar) + (Word(printables, exact=1) | White(exact=1))
216
        wordvalues = Combine(OneOrMore(wordtext | escape | '=>')).setParseAction(lambda t:t[0].replace('\xb0',''))
217
        rStart = Suppress('LIST_CUR_NE_DIR_CONF[]')
218
        rEnd = Suppress('DATA_END_NOTIF[]')
219
        response_body = Forward()
220
        response = response_body + rEnd
221
        pmCounters = Group(wordvalues + Suppress('=') + (wordvalues | (Suppress(Optional('{')) + Group(delimitedList(wordvalues, "|"))  + Suppress(Optional('}')))))
222
        pmPointBraces = Group(Suppress('{') + Dict(delimitedList(pmCounters, "|")) + Suppress('}'))
223
        pmPointsBraces = Group(Group(Suppress('{') + OneOrMore(pmPointBraces) + Suppress('}'))).setParseAction(self.setGroupPmpoints)
224
        pmPointInfo = Group(wordvalues + Suppress('=') + (wordvalues | Empty().setParseAction(replaceWith(None))))
225
        pmPointContent = Dict(delimitedList(pmPointInfo, "|")) + pmPointsBraces
226
        pmPointExpression = Group( Suppress('PM_POINT_NOTIF') + Suppress('[')+pmPointContent+Suppress(']'))
227
        allPoints = OneOrMore(pmPointExpression)
228
        response_body << allPoints
229
        d = response.parseString(data)
230
        e = d.asList()
231
        return parsePmpoints(e)
232
     
233
    def parsePmData(self, data):
234
        ''' 
235
        Pyparsing pmdata parser
236
        
237
        @type data: String
238
        @param data: Raw output from the NMS.
239
        
240
        @rtype: list of dicts
241
        @return: Transforms the NMS string into python list of dictionaries using the NMS delimiters
242
        '''
243
        escapechar = "\\"
244
        wordtext = CharsNotIn('\\*?^:"[]|={}')
245
        escape = Suppress(escapechar) + (Word(printables, exact=1) | White(exact=1))
246
        wordvalues = Combine(OneOrMore(wordtext | escape | '=>')).setParseAction(lambda t:t[0].replace('\xb0',''))
247
        rEnd = Suppress('DATA_END_NOTIF[]')
248
        response_body = Forward()
249
        response = response_body + rEnd
250
        equalityexpr = Group(wordvalues + Suppress('=') + (wordvalues | Empty().setParseAction(replaceWith(None))))
251
        dlist = Dict(delimitedList(equalityexpr, "|"))
252
        list = delimitedList(equalityexpr, "|")
253
        pmCounter = Suppress('{') + Group(Group(dlist)).setParseAction(self.setGroupCounters) + Suppress('}')
254
        pmCounterDates = Group(dlist + pmCounter)
255
        pmCounters = Group(Group(OneOrMore(pmCounterDates))).setParseAction(self.setGroupPeriods)
256
        pmCountersBraces = Suppress('{') + pmCounters + Suppress('}')
257
        pmPoint = Group(equalityexpr + pmCountersBraces)
258
        pmPoints = Group(Group(OneOrMore(pmPoint))).setParseAction(self.setGroupPmpoints)
259
        pmPointsBraces = Suppress('{') + pmPoints + Suppress('}')
260
        pmDataNotif = dlist + pmPointsBraces
261
        pmDataNotifExpr = Group( Suppress('PM_DATA_NOTIF') + Suppress('[')+pmDataNotif+Suppress(']'))
262
        pmDataAll = OneOrMore(pmDataNotifExpr)
263
        d = pmDataAll.parseString(data)
264
        e = d.asList()
265
        return parsePmpoints(e)
266

    
267
def isComplex(item):
268
    '''
269
    Simple expression to determine whether a variable is a complex (non-simple or string) list
270
    Complex list: [['a','b'], ['d','c']]
271
    Simple list: ['a', 'b', 'c']
272
    
273
    @type item: List or String
274
    @param item: The variable to be evaluated
275
    
276
    @rtype: Boolean
277
    @return: True if item is a complex list else False if item is simple list or string
278
    '''
279
    if isSimpleList(item) or isinstance(item, basestring):
280
        return False
281
    
282
    return True
283

    
284
def isSimpleList(item):
285
    '''
286
    Simple expression to determine whether a variable is a simple list
287
    Simple list: ['a', 'b', 'c']
288
    
289
    @type item: List or String
290
    @param item: The variable to be evaluated
291
    
292
    @rtype: Boolean
293
    @return: True if item is a simple list else False
294
    '''
295
    ret = False
296
    if isinstance(item, list):
297
        try:
298
            b = set(item)
299
            ret = True
300
        except:
301
            ret = False
302
    return ret
303

    
304
dictroot = {}
305
'''
306
Global dict variable that assists in transforming the pyparsing output 
307
to a python structured output
308
'''
309

    
310
def reDict(item):
311
    '''
312
    Multi-level dictionarize function. Transforms recursively lists and complex lists 
313
    into dictionaries
314
        
315
    @type item: List
316
    @param item: The variable to be evaluated
317
    
318
    @rtype: Dict
319
    @return: Dictionary of items
320
    '''
321
    if isSimpleList(item):
322
        return {item[0]: item[1]}
323
    dictroot = dict(item)
324
    for key,value in dictroot.items():
325
        if isinstance(value,list):
326
            if isComplex(value):
327
                dictroot[key] = [reDict(i) for i in value]
328
    return dictroot
329

    
330
def parsePmpoints(items):
331
    '''
332
    Parses lists of lists of lists...etc into list of dictionaries of lists or dicts...etc
333
    
334
    @type items: List of lists of lists...
335
    @param items: Output from the pyparsing function
336
    
337
    @rtype: List
338
    @return: List of dicts of lists of dicts...etc
339
    '''
340
    l = []
341
    for i in items:
342
        l.append(reDict(i))
343
    return l
344