source: branches/0.4/parse_ganglia.py @ 698

Last change on this file since 698 was 698, checked in by ramonb, 9 years ago
  • Property svn:executable set to *
File size: 8.4 KB
Line 
1#!/usr/bin/env python
2
3import shlex, sys, pprint
4from glob import glob
5
6class GangliaConfigParser:
7
8    def __init__( self, filename ):
9
10        self.conf_lijst   = [ ]
11        self.conf_dict    = { }
12        self.filename     = filename
13        self.file_pointer = file( filename, 'r' )
14        self.lexx         = shlex.shlex( self.file_pointer )
15        self.lexx.whitespace_split = True
16
17        self.parse()
18
19    def __del__( self ):
20
21        """
22        Cleanup: close file descriptor
23        """
24
25        self.file_pointer.close()
26        del self.lexx
27        del self.conf_lijst
28
29    def removeQuotes( self, value ):
30
31        clean_value = value
32        clean_value = clean_value.replace( "'", "" )
33        clean_value = clean_value.replace( '"', '' )
34        clean_value = clean_value.strip()
35   
36        return clean_value
37
38    def removeBraces( self, value ):
39
40        clean_value = value
41        clean_value = clean_value.replace( "(", "" )
42        clean_value = clean_value.replace( ')', '' )
43        clean_value = clean_value.strip()
44   
45        return clean_value
46
47    def parse( self ):
48
49        """
50        Parse self.filename using shlex scanning.
51        - Removes /* comments */
52        - Traverses (recursively) through all include () statements
53        - Stores complete valid config tokens in self.conf_list
54
55        i.e.:
56            ['globals',
57             '{',
58             'daemonize',
59             '=',
60             'yes',
61             'setuid',
62             '=',
63             'yes',
64             'user',
65             '=',
66             'ganglia',
67             'debug_level',
68             '=',
69             '0',
70             <etc> ]
71        """
72
73        t = 'bogus'
74        c = False
75        i = False
76
77        while t != self.lexx.eof:
78            #print 'get token'
79            t = self.lexx.get_token()
80
81            if len( t ) >= 2:
82
83                if len( t ) >= 4:
84
85                    if t[:2] == '/*' and t[-2:] == '*/':
86
87                        #print 'comment line'
88                        #print 'skipping: %s' %t
89                        continue
90
91                if t == '/*' or t[:2] == '/*':
92                    c = True
93                    #print 'comment start'
94                    #print 'skipping: %s' %t
95                    continue
96
97                if t == '*/' or t[-2:] == '*/':
98                    c = False
99                    #print 'skipping: %s' %t
100                    #print 'comment end'
101                    continue
102
103            if c:
104                #print 'skipping: %s' %t
105                continue
106
107            if t == 'include':
108                i = True
109                #print 'include start'
110                #print 'skipping: %s' %t
111                continue
112
113            if i:
114
115                #print 'include start: %s' %t
116
117                t2 = self.removeQuotes( t )
118                t2 = self.removeBraces( t )
119
120                for in_file in glob( self.removeQuotes(t2) ):
121
122                    #print 'including file: %s' %in_file
123                    parse_infile = GangliaConfigParser( in_file )
124
125                    self.conf_lijst = self.conf_lijst + parse_infile.getConfLijst()
126
127                    del parse_infile
128
129                i = False
130                #print 'include end'
131                #print 'skipping: %s' %t
132                continue
133
134            #print 'keep: %s' %t
135            self.conf_lijst.append( self.removeQuotes(t) )
136
137    def getConfLijst( self ):
138
139        return self.conf_lijst
140
141    def confListToDict( self, parent_list=None ):
142
143        """
144        Recursively traverses a conf_list and creates dictionary from it
145        """
146
147        new_dict = { }
148        count    = 0
149        skip     = 0
150
151        if not parent_list:
152            parent_list = self.conf_lijst
153
154        #print 'entering confListToDict(): (parent) list size %s' %len(parent_list)
155
156        for n, c in enumerate( parent_list ):
157
158            count = count + 1
159
160            #print 'CL: n %d c %s' %(n, c)
161
162            if skip > 0:
163
164                #print '- skipped'
165                skip = skip - 1
166                continue
167
168            if (n+1) <= (len( parent_list )-1):
169
170                if parent_list[(n+1)] == '{':
171
172                    if not new_dict.has_key( c ):
173                        new_dict[ c ] = [ ]
174
175                    (temp_new_dict, skip) = self.confListToDict( parent_list[(n+2):] )
176                    new_dict[ c ].append( temp_new_dict )
177
178                if parent_list[(n+1)] == '=' and (n+2) <= (len( parent_list )-1):
179
180                    if not new_dict.has_key( c ):
181                        new_dict[ c ] = [ ]
182
183                    new_dict[ c ].append( parent_list[ (n+2) ] )
184
185                    skip = 2
186
187                if parent_list[n] == '}':
188
189                    #print 'leaving confListToDict(): new dict = %s' %new_dict
190                    return (new_dict, count)
191
192
193    def makeConfDict( self ):
194
195        """
196        Walks through self.conf_list and creates a dictionary based upon config values
197
198        i.e.:
199            'tcp_accept_channel': [{'acl': [{'access': [{'action': ['"allow"'],
200                                                         'ip': ['"127.0.0.1"'],
201                                                         'mask': ['32']}]}],
202                                    'port': ['8649']}],
203            'udp_recv_channel': [{'port': ['8649']}],
204            'udp_send_channel': [{'host': ['145.101.32.3'],
205                                  'port': ['8649']},
206                                 {'host': ['145.101.32.207'],
207                                  'port': ['8649']}]}
208        """
209
210        new_dict = { }
211        skip     = 0
212
213        #print 'entering makeConfDict()'
214
215        for n, c in enumerate( self.conf_lijst ):
216
217            #print 'M: n %d c %s' %(n, c)
218
219            if skip > 0:
220
221                #print '- skipped'
222                skip = skip - 1
223                continue
224
225            if (n+1) <= (len( self.conf_lijst )-1):
226
227                if self.conf_lijst[(n+1)] == '{':
228
229                    if not new_dict.has_key( c ):
230                        new_dict[ c ] = [ ]
231
232                    ( temp_new_dict, skip ) = self.confListToDict( self.conf_lijst[(n+2):] )
233                    new_dict[ c ].append( temp_new_dict )
234
235                if self.conf_lijst[(n+1)] == '=' and (n+2) <= (len( self.conf_lijst )-1):
236
237                    if not new_dict.has_key( c ):
238                        new_dict[ c ] = [ ]
239
240                    new_dict[ c ].append( self.conf_lijst[ (n+2) ] )
241
242                    skip = 2
243
244        self.conf_dict = new_dict
245        #print 'leaving makeConfDict(): conf dict size %d' %len( self.conf_dict )
246
247    def checkConfDict( self ):
248
249        if len( self.conf_lijst ) == 0:
250
251            raise Exception("Something went wrong generating conf list for %s" %self.file_name )
252
253        if len( self.conf_dict ) == 0:
254
255            self.makeConfDict()
256
257    def getConfDict( self ):
258
259        self.checkConfDict()
260        return self.conf_dict
261
262    def getUdpSendChannels( self ):
263
264        self.checkConfDict()
265        return self.conf_dict[ 'udp_send_channel' ]
266
267    def getSectionLastOption( self, section, option ):
268
269        """
270        Get last option set in a config section that could be set multiple times in multiple (include) files.
271
272        i.e.: getSectionLastOption( 'globals', 'send_metadata_interval' )
273        """
274
275        self.checkConfDict()
276        value = None
277
278        if not self.conf_dict.has_key( section ):
279
280            return None
281
282        # Could be set multiple times in multiple (include) files: get last one set
283        for c in self.conf_dict[ section ]:
284
285                if c.has_key( option ):
286
287                    cluster_name = c[ option ][0]
288
289        return cluster_name
290
291    def getClusterName( self ):
292
293        return self.getSectionLastOption( 'cluster', 'name' )
294
295    def getVal( self, section, option ):
296
297        return self.getSectionLastOption( section, option )
298
299    def getInt( self, section, valname ):
300
301        value    = self.getVal( section, valname )
302
303        if not value:
304            return None
305
306        return int( value )
307
308    def getStr( self, section, valname ):
309
310        value    = self.getVal( section, valname )
311
312        if not value:
313            return None
314
315        return str( value )
316
317GMOND_LOCATION = '/etc/ganglia/gmond.conf'
318
319g = GangliaConfigParser( GMOND_LOCATION )
320
321pprint.pprint( g.getConfLijst(), width=1 )
322
323g.makeConfDict()
324
325pprint.pprint( g.getConfDict(), width=1 )
326
327print g.getClusterName()
328print g.getUdpSendChannels()
329
330print 'exiting..'
331sys.exit(0)
Note: See TracBrowser for help on using the repository browser.