1 # Copyright 2012 Leonidas Poulopoulos
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 from pyparsing import *
21 Subclass of eos to connect to the PM subsystem
24 def __init__(self, server=None, port=None, password=None):
27 Constructor for the class.
30 @param server: The Hostname or IPv4 address of the Alcatel NMS.
33 @param port: The TCP port on the Alcatel NMS we will connect to.
35 @type password: String
36 @param password: The password for this connection.
39 @return: A connection handler of this class.
43 return eos.__init__(self, server, port, password)
45 def list_pm_data(self, startPeriod=None, endPeriod=None, neName=[], periodType=None, counters=[], pmPoints=[], parse=True):
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
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',
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',
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.
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.
76 @type neName: A list of strings
77 @param neName: A list of NetworkElement names with pmPoints assigned. If omitted all NEs are assumed
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
82 @type counters: A list of strings
83 @param counters: The counters for the above NetworkElements to fetch. If omitted all counters
85 @type pmPoints: A list of strings
86 @param pmPoints: The counters for the above NetworkElements to fetch. If omitted all counters
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.
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.
95 extras.append('periodType=%s'%(periodType) if periodType else '')
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 neName])) if neName else '')
101 params = "|".join(extras) or ''
102 message = "LIST_PM_DATA_REQ[%s]" %params
103 if self.send(message) == 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)
110 if reply == "DATA_END_NOTIF[]":
113 ret = self.parsePmData(reply)
119 def list_pm_point(self, neNames=[], periodType=None, period=None, parse=True, listAll=False):
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
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',
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',
144 @type neNames: A list of strings
145 @param neNames: A list of NetworkElement names with pmPoints assigned. If omitted, all NEs are assumed
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
151 @param period: Period during which pm points were collected. Format: YYYYMMDDQH where QH in [00,96] representing 15min periods in a day.
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.
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
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.
163 extras.append('%s'%(periodType) if periodType else '')
164 extras.append('%s'%(period) if period else '')
165 extras.append('{%s}'%(('|'.join(neNames)) if neNames else ''))
166 params = "|".join(extras) or ''
169 message = "LIST_PM_POINT_REQ[%s]" %params
170 if self.send(message) == 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)
177 if reply == "DATA_END_NOTIF[]":
180 ret = self.parsePmPoint(reply)
185 def setGroupCounters(self, l, s, toks):
187 Pyparsing action parser to include counters as key in pmPoint parsing
189 return [["counters", toks[0][0].asList()]]
191 def setGroupPmpoints(self, l, s, toks):
193 Pyparsing action parser to include pmpoints as key in pmPoint parsing
195 return [["pmpoints", toks[0][0].asList()]]
197 def setGroupPeriods(self, l, s, toks):
199 Pyparsing action parser to include periods as key in pmPoint parsing
201 return [["periods", toks[0][0].asList()]]
203 def parsePmPoint(self, data):
205 Pyparsing pmpoint parser
208 @param data: Raw output from the NMS.
210 @rtype: list of dicts
211 @return: Transforms the NMS string into python list of dictionaries using the NMS delimiters
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)
231 return parsePmpoints(e)
233 def parsePmData(self, data):
235 Pyparsing pmdata parser
238 @param data: Raw output from the NMS.
240 @rtype: list of dicts
241 @return: Transforms the NMS string into python list of dictionaries using the NMS delimiters
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)
265 return parsePmpoints(e)
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']
273 @type item: List or String
274 @param item: The variable to be evaluated
277 @return: True if item is a complex list else False if item is simple list or string
279 if isSimpleList(item) or isinstance(item, basestring):
284 def isSimpleList(item):
286 Simple expression to determine whether a variable is a simple list
287 Simple list: ['a', 'b', 'c']
289 @type item: List or String
290 @param item: The variable to be evaluated
293 @return: True if item is a simple list else False
296 if isinstance(item, list):
306 Global dict variable that assists in transforming the pyparsing output
307 to a python structured output
312 Multi-level dictionarize function. Transforms recursively lists and complex lists
316 @param item: The variable to be evaluated
319 @return: Dictionary of items
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):
327 dictroot[key] = [reDict(i) for i in value]
330 def parsePmpoints(items):
332 Parses lists of lists of lists...etc into list of dictionaries of lists or dicts...etc
334 @type items: List of lists of lists...
335 @param items: Output from the pyparsing function
338 @return: List of dicts of lists of dicts...etc