source: ccsd/trunk/crcnetd/modules/ccs_rrdbot.py @ 1269

Last change on this file since 1269 was 1269, checked in by ckb6, 6 years ago

This commit contains the ccsd side of minipulating snmp instructions and snmp state. This is used as a link between ccsd and the polling system (rrdbot-script)

  • Property svn:keywords set to Id
File size: 12.6 KB
Line 
1# Copyright (C) 2006  The University of Waikato
2#
3# This file is part of crcnetd - CRCnet Configuration System Daemon
4#
5# This handles the rrdbot service.
6#
7# Author:       Chris Browning <ckb6@cs.waikato.ac.nz>
8# Version:      $Id$
9#
10# crcnetd is free software; you can redistribute it and/or modify it under the
11# terms of the GNU General Public License version 2 as published by the Free
12# Software Foundation.
13#
14# crcnetd is distributed in the hope that it will be useful, but WITHOUT ANY
15# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17# details.
18#
19# You should have received a copy of the GNU General Public License along with
20# crcnetd; if not, write to the Free Software Foundation, Inc.,
21# 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22from crcnetd._utils.ccsd_common import *
23from crcnetd._utils.ccsd_log import *
24from crcnetd._utils.ccsd_events import *
25from crcnetd._utils.ccsd_session import getSession, getSessionE
26from crcnetd._utils.ccsd_server import exportViaXMLRPC
27from crcnetd._utils.ccsd_service import ccsd_service, ccs_service_error, \
28        registerService
29
30import time
31
32ccs_mod_type = CCSD_SERVER
33
34@exportViaXMLRPC(SESSION_RW, AUTH_USER)
35def snmp_found(session_id, hostname, classname, number, data=''):
36    '''Callback from rrdbot-script reporting a class instance'''
37
38    session = getSessionE(session_id)
39    sql = "SELECT a.host_id, b.class_id FROM host a , rrdbot_class b WHERE a.host_name=%s and b.class_name=%s"
40    res = session.query(sql, (hostname,classname)) 
41    host_id = res[0]["host_id"]
42    class_id = res[0]["class_id"]
43    link_id = 0;
44
45    #Attempt tp assciate the data to a link
46    if data != '':
47        sql = "SELECT link_id FROM interface WHERE ip_address=%s"
48        res = session.query(sql, (data))
49        if res:
50            link_id = res[0]["link_id"]
51
52    #Check to see if this class has been found before
53    sql = "SELECT num FROM snmp_discovery WHERE host_id=%s AND class_id=%s AND num=%s"
54    res = session.query(sql, (host_id, class_id, number))
55    #If the class exists update it else add it
56    if len(res) > 0:
57        sql = "UPDATE snmp_discovery SET ip_address=%s, link_id=%s, timestamp=current_timestamp \
58            WHERE host_id=%s AND class_id=%s AND num=%s"
59        session.execute(sql, (data, link_id, host_id, class_id, number))
60    else:   
61        sql = "INSERT INTO snmp_discovery VALUES(%s, %s, %s, %s, %s, current_timestamp)"       
62        session.execute(sql, (host_id, class_id, number, data, link_id))
63    return 1
64
65@exportViaXMLRPC(SESSION_RW, AUTH_USER)
66def addSnmpInstruction(session_id, host_id, instr, param1=None, param2=None, param3=None):
67    '''Adds an instruction that rrdbot-script will deal with'''
68
69    session = getSessionE(session_id)
70    sql = "INSERT INTO snmp_instructions VALUES(%s, %s, %s, %s, %s)"       
71    session.execute(sql, (host_id, instr, param1, param2, param3))
72    return 1
73   
74@exportViaXMLRPC(SESSION_RW, AUTH_USER)
75def getSnmpInstructions(session_id):
76    '''Get all all snmp instructions'''
77    instrs = {1:"Probe for Timed out class", 2:"Probe for Timed out class instance", 3:"Re-probe host"}
78    session = getSessionE(session_id)
79    sql = "SELECT a.*, b.host_name FROM snmp_instructions a , host b WHERE b.host_id=a.host_id"
80    res = session.query(sql, ())
81    for r in res:
82        if r["instr"] in instrs.keys():
83            r["instr_name"] = instrs[r["instr"]]
84        else:
85            r["instr_name"] = "Unknowen"
86    return res
87   
88@exportViaXMLRPC(SESSION_RW, AUTH_USER)
89def setSnmpState(session_id,state):
90    '''Set the current state of rrdbot-script'''
91
92    session = getSessionE(session_id)
93    sql = "UPDATE snmp_state SET state=%s"
94    res = session.execute(sql, (state))
95    if res and res[0][0] == 0:
96        return round(300-(time.time()%300))
97    else:
98        return 0   
99       
100@exportViaXMLRPC(SESSION_RO, AUTH_USER)
101def getSnmpState(session_id):
102    '''Get the current state of rrdbot-script'''
103
104    session = getSessionE(session_id)
105    sql = "SELECT state FROM snmp_state"
106    res = session.query(sql, ())
107    if res and res[0][0] == 0:
108        return round(300-(time.time()%300))
109    else:
110        return 0
111@exportViaXMLRPC(SESSION_RW, AUTH_USER)
112def flushSnmpInstructions(session_id):
113    '''Clear all snmp instructions'''
114
115    session = getSessionE(session_id)
116    sql = "DELETE FROM snmp_instructions"
117    session.execute(sql, ())
118    return 1   
119   
120@exportViaXMLRPC(SESSION_RW, AUTH_USER)
121def addClass(session_id, clas):
122    """Adds a new class to the database"""
123    session = getSessionE(session_id)
124   
125    # Build query
126    props = ["class_name", "poll", "interval", \
127            "cf", "archive", "depends"]
128    (sql, values) = buildInsertFromDict("rrdbot_class", props, clas)
129   
130    # Run query
131    session.execute(sql, values)
132
133    return 1
134   
135@exportViaXMLRPC(SESSION_RW, AUTH_USER)
136def addClassPart(session_id, part):
137    """Adds a new class part to the database"""
138    session = getSessionE(session_id)
139   
140    # Build query
141    props = ["class_id", "name", "poll", "type", \
142        "min", "max"]
143       
144    nulls= []
145
146    if "min" in part and part["min"] == '':
147        nulls.append("min")
148    if "max" in part and part["max"] == '':
149        nulls.append("max")
150
151    (sql, values) = buildInsertFromDict("rrdbot_class_parts", props, part, False, nulls)
152   
153    # Run query
154    session.execute(sql, values)
155
156    return 1
157   
158@exportViaXMLRPC(SESSION_RW, AUTH_ADMINISTRATOR)
159def removeClass(session_id, class_id):
160    """Removes class from the database."""
161    session = getSessionE(session_id)
162   
163    #First remove any dependants
164    sql = "SELECT * FROM rrdbot_class WHERE depends=%s"
165
166    res = session.query(sql, (class_id))
167    for clas in res:
168        sql = "UPDATE rrdbot_class SET depends=0, poll=\'%s%s\' WHERE class_id=%%s" % (clas["poll"], ":exist")
169        res2 = session.execute(sql, (clas["class_id"]))
170        print sql
171        print clas["class_id"]
172   
173    # Delete the class and its class parts
174    sql = "DELETE FROM rrdbot_class WHERE class_id=%s"
175    res = session.execute(sql, (class_id))
176    sql = "DELETE FROM rrdbot_class_parts WHERE class_id=%s"
177    res = session.execute(sql, (class_id))
178    return 1
179   
180@exportViaXMLRPC(SESSION_RW, AUTH_ADMINISTRATOR)
181def updateClassDetails(session_id, class_id, newDetails):
182    """Updates the details of the Class.
183
184    newDetails should be a dictionary containing only these class paramters
185    that have changed and need to be updated in the database.
186    """
187    session = getSessionE(session_id)
188       
189    # Build SQL
190    props = ["class_id", "class_name", "poll", "interval", \
191        "cf", "archive", "depends"]
192    (sql, values) = buildUpdateFromDict("rrdbot_class", props, newDetails, \
193            "class_id", class_id)
194       
195    if values == None:
196        # No changes made... ?
197        return 1
198   
199    # Run the query
200    session.execute(sql, values)
201   
202    return 1
203   
204@exportViaXMLRPC(SESSION_RW, AUTH_ADMINISTRATOR)
205def updateClassPartDetails(session_id, part_id, newDetails):
206    """Updates the details of the Class part.
207
208    newDetails should be a dictionary containing only these class paramters
209    that have changed and need to be updated in the database.
210    """
211    session = getSessionE(session_id)
212       
213    # Build SQL
214    props = ["part_id", "class_id", "name", "poll", "type", \
215        "min", "max"]
216    nulls= []
217
218    if "min" in newDetails and newDetails["min"] == '':
219        nulls.append("min")
220    if "max" in newDetails and newDetails["max"] == '':
221        nulls.append("max")
222
223    (sql, values) = buildUpdateFromDict("rrdbot_class_parts", props, newDetails, \
224            "part_id", part_id,False,nulls)
225       
226    if values == None:
227        # No changes made... ?
228        return 1
229   
230    # Run the query
231    session.execute(sql, values)
232
233    return 1 
234   
235@exportViaXMLRPC(SESSION_RO, AUTH_USER)
236def listClasses(session_id):
237    """Returns a list of classes"""
238    session = getSessionE(session_id)
239       
240    # Build SQL
241    sql = "SELECT * FROM rrdbot_class"   
242   
243    # Run the query
244    res = session.query(sql, ())
245    return res
246   
247@exportViaXMLRPC(SESSION_RO, AUTH_USER)
248def getClass(session_id,class_id):
249    """Returns a class"""
250    session = getSessionE(session_id)
251       
252    # Build SQL
253    sql = "SELECT * FROM rrdbot_class WHERE class_id=%s"   
254   
255    # Run the query
256    res = session.query(sql, (class_id))
257    return res
258   
259@exportViaXMLRPC(SESSION_RO, AUTH_USER)
260def getClassDepends(session_id,class_id):
261    """Returns a list of classes this class could be set to depend on"""
262    session = getSessionE(session_id)   
263    #If new class flag is set do a custom query
264    if class_id == -1:
265         # Build SQL
266        sql = "SELECT * FROM rrdbot_class WHERE depends=0"   
267   
268        # Run the query
269        res = session.query(sql, ())
270
271        return res
272
273    # Build SQL
274    sql = "SELECT * FROM rrdbot_class WHERE depends=%s"   
275   
276    # Run the query
277    res = session.query(sql, (class_id))
278
279    #If class is depended on it can depend on somthing else
280    if len(res) > 0:
281        return []
282
283    # Build SQL
284    sql = "SELECT * FROM rrdbot_class WHERE class_id!=%s AND depends=0"   
285   
286    # Run the query
287    res = session.query(sql, (class_id))
288
289    return res 
290   
291@exportViaXMLRPC(SESSION_RO, AUTH_USER)
292def getClassParts(session_id,class_id):
293    """Returns a list of Class parts"""
294    session = getSessionE(session_id)
295   
296    # Build SQL
297    sql = "SELECT * FROM rrdbot_class_parts WHERE class_id=%s"   
298   
299    # Run the query
300    res = session.query(sql, (class_id))
301    return res
302   
303@exportViaXMLRPC(SESSION_RO, AUTH_ADMINISTRATOR)
304def getClassPart(session_id, part_id):
305    """Returns a class part"""
306    session = getSessionE(session_id)
307   
308    # Build SQL
309    sql = "SELECT * FROM rrdbot_class_parts WHERE part_id=%s"   
310   
311    # Run the query
312    res = session.query(sql, (part_id))
313    return res
314
315@exportViaXMLRPC(SESSION_RW, AUTH_ADMINISTRATOR)
316def removeClassPart(session_id, part_id):
317    """Removes class part from the database."""
318    session = getSessionE(session_id)
319   
320    # Delete the class part
321    sql = "DELETE FROM rrdbot_class_parts WHERE part_id=%s"
322    res = session.execute(sql, (part_id))
323    return 1
324   
325class ccs_rrdbot(ccsd_service):
326
327    serviceName = "rrdbot"
328    networkService = True
329
330    def __init__(self, session_id, service_id):
331        # Call base class setup
332        ccsd_service.__init__(self, session_id, service_id)
333
334
335    def getNetworkTemplateVariables(self):
336        """Returns a dictionary containing template variables.
337
338        WARNING: The returned dictionary could be very large!
339        """
340        variables = ccsd_service.getNetworkTemplateVariables(self)
341        session = getSessionE(ADMIN_SESSION_ID)
342        res = session.query("SELECT * FROM rrdbot_class",())
343        classes = {};
344        for clas in res:
345            clas["variables"] = session.query("SELECT * FROM \
346                rrdbot_class_parts WHERE class_id=%s",(clas["class_id"]))
347            if clas["depends"] != 0:
348                if clas["depends"] in classes:
349                    classes[clas["depends"]]["subs"].append(clas)
350                else:
351                    classes[clas["depends"]] = {}
352                    classes[clas["depends"]]["subs"] = []
353                    classes[clas["depends"]]["subs"].append(clas)
354            else:
355                classes[clas["class_id"]] = clas
356                classes[clas["class_id"]]["subs"] = []
357
358
359        variables['classes'] = classes
360        return variables
361       
362    @staticmethod
363    def initialiseService():
364        """Called by the system the very first time the service is loaded.
365
366        This should setup an entry in the service table and load any default
367        service properties into the service_prop table.
368        """
369        session = getSessionE(ADMIN_SESSION_ID)
370        session.begin("initialising rrdbot service")       
371        try:
372
373            session.execute("INSERT INTO service (service_id, service_name, " \
374                    "enabled) VALUES (DEFAULT, %s, DEFAULT)", \
375                    (ccs_rrdbot.serviceName))
376            service_id = session.getCountOf("SELECT currval('" \
377                    "service_service_id_seq') AS server_id", ())
378
379            # Commit the changeset
380            session.commit()
381           
382            log_info("Created rrdbot service entries and tables in database")
383        except:
384            session.rollback()
385            log_error("Unable to initialise rrdbot database entries!", \
386                    sys.exc_info())
387            raise quagga_error("Failed to setup database tables!")
388
389        return service_id
390
391       
392def ccs_init():
393    registerService(ccs_rrdbot)
Note: See TracBrowser for help on using the repository browser.