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 getLength(self, from_interface): """Returns the length in metres of the link from the named interface If there are multiple peer interfaces on the link, the length returned is the length to the most distance interface. The length is calculated using the great circle distance based on the GPS co-ordinates of the two sites where the host containing the interface is located. If GPS information is not available for either end the link is set to a default value of 20000m. The default value can be modified via the default_link_length configuration file parameter """ session = getSessionE(self._session_id) orig = None orig_lat = 0 orig_long = 0 peers = [] length = 0 # Get the default link length default_link_length = config_getint("network", "default_link_length", DEFAULT_LINK_LENGTH) if default_link_length < MIN_DEFAULT_LINK_LENGTH: log_error("Invalid default link length! Must be > %sm" % MIN_DEFAULT_LINK_LENGTH) default_link_length = DEFAULT_LINK_LENGTH # Select the interface co-ordinates for all interfaces on this link res = session.query("SELECT * FROM interface_gpslocation WHERE " "link_id=%s", (self.link_id)) if len(res) < 2: return default_link_length for iface in res: # No GPS co-ords available if iface["gps_lat"] <= 0 or iface["gps_long"] <= 0: return default_link_length this_lat = iface["gps_lat"] this_long = iface["gps_long"] if iface["interface_id"] == from_interface: try: orig = nav.GeoPoint() orig.set_latitude_dec(this_lat) orig.set_longitude_dec(this_long) except: log_warn("Invalid co-ordinates for interface %s" % from_interface, sys.exc_info()) return default_link_length else: peers.append((this_lat, this_long)) if orig is not None: # Calculate distance while peers != []: lat, long = peers.pop() try: peer = nav.GeoPoint() peer.set_latitude_dec(lat) peer.set_longitude_dec(long) except: log_warn("Invalid co-ordinates for interface", sys.exc_info()) return default_link_length # Round the length up to the nearest integer and convert # to metres plength = int(ceil(orig.get_distance_to(peer) * 1000)) if plength > length: length = plength # Check that at least one distance was calculated if length == 0: length = default_link_length return length