def ccs_init(): global debug_snmp # Default SNMP Content Helpers # Implement the basics of the SNMPv2-MIB SNMPv2_MIB = (1,3,6,1,2,1,1) registerStaticOID(SNMPv2_MIB+(1,0), "CRCnet Monitor v%s (r%s), %s" % \ (ccsd_version, ccsd_revision, " ".join(os.uname())), "OctetString") # sysObjectID not implemented UPTIME_START = time.time() @registerDynamicOID(SNMPv2_MIB+(3,0)) def uptime(oid, getNext): if getNext: return None uptime = (time.time()-UPTIME_START)*100 return (oid, TimeTicks(uptime)) # sysContact not implemented registerStaticOID(SNMPv2_MIB+(5,0), socket.gethostname(), "OctetString") # sysLocation not implemented # sysServices not implemented # sysOR not implemented # Start the actual SNMP server try: debug_snmp = config_getboolean("snmp", "debug", False) port = int(config_get("snmp", "port", DEFAULT_SNMP_PORT)) AsyncSNMPServer(('', port)) log_info("SNMP Server Started") except: log_fatal("Could not initialise the SNMP server!", sys.exc_info())
def homepage(request, method): # MOTD at the top liveMOTD = config_getboolean("www", "liveMOTD", False) homepage = config_get("www", "motdHomepage", "http://www.crc.net.nz") if liveMOTD: output = """<div class="content" id="motd">""" output += "<h2>Loading Latest News...</h2><br />" output += "Please wait while the latest news is retrieved." else: output = """<div class="content">""" output += "<h2>Latest News</h2><br />" output += "To keep up to date with the latest news " output += "please visit the homepage at " output += """<a href="%s">%s</a>""" % (homepage, homepage) output += "</div>" # Try and load the status summary from the status module try: from crcnetd.modules.ccs_monitor_status import getStatusSummary status = getStatusSummary() except: log_warn("Could not retrieve status summary", sys.exc_info()) status = "CPE Status not available" # CPE Status output += """<div class="content"> <h2>CPE Status</h2><br /> %s </div> """ % status returnPage(request, "CPE Navigation", output, scripts=["/resources/homepage.js"])
def statusThread(): """Runs as a thread to keep the status information up to date""" global _statusInfo, _runStatus try: # Is status checking enabled enabled = config_getboolean("status", "enabled", True) if not enabled: log_info("Status checking disabled. Exiting status monitor thread") return _runStatus = True; # Setup the thread information ct = threading.currentThread() ct.setName("CCSD Status Monitor") # What interval shall we check hosts at interval = config_get("status", "interval", DEFAULT_CHECK_INTERVAL) # Initialise the host status information hosts = getHostList(ADMIN_SESSION_ID) for host in getHostList(ADMIN_SESSION_ID): if not host["host_active"]: continue name = host["host_name"] _statusInfo[name] = ccs_host_status(ADMIN_SESSION_ID, \ host["host_id"], interval) # Loop forever reading status as appropriate while _runStatus: # wait a bit before checking time.sleep(2) # Does the queue have entries if len(ccs_host_status.update_queue) <= 0: continue # Is the first entry valid if len(ccs_host_status.update_queue[0]) != 2: log_error("Invalid entry in status update queue! - %s" % ccs_host_status.update_queue[0]) ccs_host_status.update_queue.pop(0) continue # Check if it's ready to run if ccs_host_status.update_queue[0][0] > time.time(): continue # Read to run check = ccs_host_status.update_queue.pop(0) try: check[1].update() except: log_error("Failed to update status of %s" % \ check[1]._hostname, sys.exc_info()) # Regardless of what happened, check again sometime soon if it # is still in the list of hosts to check if check[1]._hostname in _statusInfo.keys(): check[1].requeue() except: log_error("Exception in status monitor thread!", sys.exc_info()) log_info("Exiting status monitor thread")
def ifAccountThread(): """Runs as a thread to account from traffic on an interface""" global _accountingInfo, _runIfAccount, nas_id, nas_ip global radius_update_interval, radius_acct_server, radius_auth_server try: # Is interface accounting enabled enabled = config_getboolean("accounting", "enabled", True) if not enabled: log_info("Interface accounting disabled.") return _runIfAccount = True # What interval shall we check hosts at check_interval = config_get("accounting", "check_interval", DEFAULT_CHECK_INTERVAL) radius_update_interval = config_getint("accounting", "update_interval", DEFAULT_UPDATE_INTERVAL) # Initialise the interface list default_user_file = "%s/accounting_users" % os.path.dirname(DEFAULT_CONFFILE) user_file = config_get("accounting", "user_file", default_user_file) if not os.path.exists(user_file): log_error("Interface accounting disabled. No user file: %s" % user_file) _runIfAccount = False return # Initialise the RADIUS connection try: dummy0 = getInterfaces(returnOne="dummy0")[0] dummy0ip = dummy0["address"].split("/")[0] except: log_error("Could not determine host loopback address!", sys.exc_info()) dummy0ip = "127.0.0.1" acct_server = config_get("accounting", "acct_server", "radius") acct_secret = config_get_required("accounting", "acct_secret") auth_server = config_get("accounting", "auth_server", "radius") auth_secret = config_get_required("accounting", "auth_secret") nas_id = config_get("accounting", "nas_id", getFQDN()) nas_ip = config_get("accounting", "nas_ip", dummy0ip) radius_acct_server = Client(server=acct_server, secret=acct_secret, dict=Dictionary(RADIUS_DICTIONARY)) radius_auth_server = Client(server=auth_server, secret=auth_secret, dict=Dictionary(RADIUS_DICTIONARY)) # FreeRADIUS at least auths based on IP address, make sure our # packets come from the right place radius_acct_server.bind((nas_ip, 0)) radius_auth_server.bind((nas_ip, 0)) # Read and parse the user file parseUserFile(user_file) # Initialise interface state initialiseInterfaceState() # Loop forever reading byte counters as appropriate while _runIfAccount: # wait a bit before checking time.sleep(check_interval) # Send any queued packets processRADIUSQueue() # Try and re-authenticate any dead interfaces for ifname, iface in _accountingInfo.items(): if iface["authenticated"]: continue age = time.time() - iface["last_auth_check"] if age > radius_update_interval: doRADIUSAuthentication(ifname) # Update traffic details updateTrafficCounters() # Generate interim-updates processInterimUpdates() except: (etype, value, tb) = sys.exc_info() log_error("Exception in interface accounting thread! - %s" % value, (etype, value, tb)) log_info("Exiting interface accounting thread")
def getMOTD(request, method): """Returns HTML to display the Message of the Day""" tmpdir = config_get(None, "tmpdir", DEFAULT_TMPDIR) motdFile = "%s/motd" % tmpdir motdRefreshInterval = config_get("www", "motd_refresh", \ DEFAULT_MOTD_REFRESH) motdURL = config_get("www", "motdURL", DEFAULT_MOTD_URL) fetchMotd = config_getboolean("www", "fetch_motd", False) updateNote = "" try: mtime = os.stat(motdFile)[8] except: mtime = -1 if (mtime == -1 or time.time()-mtime > motdRefreshInterval or \ request.query.find("refreshMotd=true") != -1) and fetchMotd: # Get new MOTD try: o = urllib.URLopener() o.addheaders = [("User-agent", "crcnet-monitor/%s (r%s)" % \ (ccsd_version, ccsd_revision))] wfd = o.open(motdURL) fd = open(motdFile, "w") motd = wfd.read() fd.write(motd) fd.close wfd.close() mtime = time.time() except: log_error("Unable to fetch MOTD", sys.exc_info()) motd = "Unable to retrieve latest news." mtime = -1 else: try: fd = open(motdFile, "r") motd = fd.read() fd.close() except: motd = "No news available" # Calculate how long till next update if mtime != -1: updateAtSecs = (mtime + motdRefreshInterval) - time.time() updateAt = formatTime(updateAtSecs) retrieved = time.ctime(mtime) updateNote = "Retrieved at %s, next update in %s" % (retrieved, updateAt) # Generate the output output = """<h2>Latest News <span class="note">%s <a href="/?refreshMotd=true">[Refresh Now]</a> </span> </h2><br /> %s """ % (updateNote, motd.replace("\n", "<br />")) length = len(output) request.send_response(200) request.send_header("Length", length) request.end_headers() request.wfile.write(output) request.finish() return