Adding hooks for socket reporting.
NOT WORKING YET… but it is a start
This commit is contained in:
parent
f9c4b78b45
commit
df264042d6
|
@ -48,6 +48,7 @@ def build_config(_config_file):
|
||||||
|
|
||||||
CONFIG = {}
|
CONFIG = {}
|
||||||
CONFIG['GLOBAL'] = {}
|
CONFIG['GLOBAL'] = {}
|
||||||
|
CONFIG['REPORTS'] = {}
|
||||||
CONFIG['LOGGER'] = {}
|
CONFIG['LOGGER'] = {}
|
||||||
CONFIG['ALIASES'] = {}
|
CONFIG['ALIASES'] = {}
|
||||||
CONFIG['AMBE'] = {}
|
CONFIG['AMBE'] = {}
|
||||||
|
@ -62,6 +63,14 @@ def build_config(_config_file):
|
||||||
'MAX_MISSED': config.getint(section, 'MAX_MISSED')
|
'MAX_MISSED': config.getint(section, 'MAX_MISSED')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
elif section == 'REPORTS':
|
||||||
|
CONFIG['REPORTS'].update({
|
||||||
|
'REPORT': config.getboolean(section, 'REPORT'),
|
||||||
|
'REPORT_INTERVAL': config.getint(section, 'REPORT_INTERVAL'),
|
||||||
|
'REPORT_PORT': config.getint(section, 'REPORT_PORT'),
|
||||||
|
'REPORT_CLIENTS': config.get(section, 'REPORT_CLIENTS').split(',')
|
||||||
|
})
|
||||||
|
|
||||||
elif section == 'LOGGER':
|
elif section == 'LOGGER':
|
||||||
CONFIG['LOGGER'].update({
|
CONFIG['LOGGER'].update({
|
||||||
'LOG_FILE': config.get(section, 'LOG_FILE'),
|
'LOG_FILE': config.get(section, 'LOG_FILE'),
|
||||||
|
|
|
@ -9,6 +9,26 @@ PATH: ./
|
||||||
PING_TIME: 5
|
PING_TIME: 5
|
||||||
MAX_MISSED: 3
|
MAX_MISSED: 3
|
||||||
|
|
||||||
|
|
||||||
|
# NOT YET WORKING: NETWORK REPORTING CONFIGURATION
|
||||||
|
# Enabling "REPORT" will configure a socket-based reporting
|
||||||
|
# system that will send the configuration and other items
|
||||||
|
# to a another process (local or remote) that may process
|
||||||
|
# the information for some useful purpose, like a web dashboard.
|
||||||
|
#
|
||||||
|
# REPORT - True to enable, False to disable
|
||||||
|
# REPORT_INTERVAL - Seconds between reports
|
||||||
|
# REPORT_PORT - TCP port to listen on if "REPORT_NETWORKS" = NETWORK
|
||||||
|
# REPORT_CLIENTS - comma separated list of IPs you will allow clients
|
||||||
|
# to connect on. Entering a * will allow all.
|
||||||
|
#
|
||||||
|
[REPORTS]
|
||||||
|
REPORT: False
|
||||||
|
REPORT_INTERVAL: 60
|
||||||
|
REPORT_PORT: 4321
|
||||||
|
REPORT_CLIENTS: 127.0.0.1
|
||||||
|
|
||||||
|
|
||||||
# SYSTEM LOGGER CONFIGURAITON
|
# SYSTEM LOGGER CONFIGURAITON
|
||||||
# This allows the logger to be configured without chaning the individual
|
# This allows the logger to be configured without chaning the individual
|
||||||
# python logger stuff. LOG_FILE should be a complete path/filename for *your*
|
# python logger stuff. LOG_FILE should be a complete path/filename for *your*
|
||||||
|
|
79
hblink.py
79
hblink.py
|
@ -39,15 +39,19 @@ from bitstring import BitArray
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
# Twisted is pretty important, so I keep it separate
|
# Twisted is pretty important, so I keep it separate
|
||||||
from twisted.internet.protocol import DatagramProtocol
|
from twisted.internet.protocol import DatagramProtocol, Factory, Protocol
|
||||||
from twisted.internet import reactor
|
from twisted.protocols.basic import NetstringReceiver
|
||||||
from twisted.internet import task
|
from twisted.internet import reactor, task
|
||||||
|
|
||||||
# Other files we pull from -- this is mostly for readability and segmentation
|
# Other files we pull from -- this is mostly for readability and segmentation
|
||||||
import hb_log
|
import hb_log
|
||||||
import hb_config
|
import hb_config
|
||||||
from dmr_utils.utils import int_id, hex_str_4
|
from dmr_utils.utils import int_id, hex_str_4
|
||||||
|
|
||||||
|
# Imports for the reporting server
|
||||||
|
import cPickle as pickle
|
||||||
|
from reporting_const import *
|
||||||
|
|
||||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||||
__copyright__ = 'Copyright (c) 2016 Cortney T. Buffington, N0MJS and the K0USY Group'
|
__copyright__ = 'Copyright (c) 2016 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||||
|
@ -60,6 +64,25 @@ __email__ = 'n0mjs@me.com'
|
||||||
# Global variables used whether we are a module or __main__
|
# Global variables used whether we are a module or __main__
|
||||||
systems = {}
|
systems = {}
|
||||||
|
|
||||||
|
# Timed loop used for reporting IPSC status
|
||||||
|
#
|
||||||
|
# REPORT BASED ON THE TYPE SELECTED IN THE MAIN CONFIG FILE
|
||||||
|
def config_reports(_config, _logger, _factory):
|
||||||
|
if _config['REPORTS']['REPORT']:
|
||||||
|
def reporting_loop(_logger, _server):
|
||||||
|
_logger.debug('Periodic reporting loop started')
|
||||||
|
_server.send_config()
|
||||||
|
|
||||||
|
_logger.info('HBlink TCP reporting server configured')
|
||||||
|
|
||||||
|
report_server = _factory(_config, _logger)
|
||||||
|
report_server.clients = []
|
||||||
|
reactor.listenTCP(_config['REPORTS']['REPORT_PORT'], report_server)
|
||||||
|
|
||||||
|
reporting = task.LoopingCall(reporting_loop, _logger, report_server)
|
||||||
|
reporting.start(_config['REPORTS']['REPORT_INTERVAL'])
|
||||||
|
|
||||||
|
|
||||||
# Shut ourselves down gracefully by disconnecting from the masters and clients.
|
# Shut ourselves down gracefully by disconnecting from the masters and clients.
|
||||||
def hblink_handler(_signal, _frame, _logger):
|
def hblink_handler(_signal, _frame, _logger):
|
||||||
for system in systems:
|
for system in systems:
|
||||||
|
@ -469,6 +492,53 @@ class HBSYSTEM(DatagramProtocol):
|
||||||
else:
|
else:
|
||||||
self._logger.error('(%s) Received an invalid command in packet: %s', self._system, ahex(_data))
|
self._logger.error('(%s) Received an invalid command in packet: %s', self._system, ahex(_data))
|
||||||
|
|
||||||
|
#
|
||||||
|
# Socket-based reporting section
|
||||||
|
#
|
||||||
|
class report(NetstringReceiver):
|
||||||
|
def __init__(self, factory):
|
||||||
|
self._factory = factory
|
||||||
|
|
||||||
|
def connectionMade(self):
|
||||||
|
self._factory.clients.append(self)
|
||||||
|
self._factory._logger.info('HBlink reporting client connected: %s', self.transport.getPeer())
|
||||||
|
|
||||||
|
def connectionLost(self, reason):
|
||||||
|
self._factory._logger.info('HBlink reporting client disconnected: %s', self.transport.getPeer())
|
||||||
|
self._factory.clients.remove(self)
|
||||||
|
|
||||||
|
def stringReceived(self, data):
|
||||||
|
self.process_message(data)
|
||||||
|
|
||||||
|
def process_message(self, _message):
|
||||||
|
opcode = _message[:1]
|
||||||
|
if opcode == REPORT_OPCODES['CONFIG_REQ']:
|
||||||
|
self._factory._logger.info('HBlink reporting client sent \'CONFIG_REQ\': %s', self.transport.getPeer())
|
||||||
|
self.send_config()
|
||||||
|
else:
|
||||||
|
self._factory._logger.error('got unknown opcode')
|
||||||
|
|
||||||
|
class reportFactory(Factory):
|
||||||
|
def __init__(self, config, logger):
|
||||||
|
self._config = config
|
||||||
|
self._logger = logger
|
||||||
|
|
||||||
|
def buildProtocol(self, addr):
|
||||||
|
if (addr.host) in self._config['REPORTS']['REPORT_CLIENTS'] or '*' in self._config['REPORTS']['REPORT_CLIENTS']:
|
||||||
|
self._logger.debug('Permitting report server connection attempt from: %s:%s', addr.host, addr.port)
|
||||||
|
return report(self)
|
||||||
|
else:
|
||||||
|
self._logger.error('Invalid report server connection attempt from: %s:%s', addr.host, addr.port)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def send_clients(self, _message):
|
||||||
|
for client in self.clients:
|
||||||
|
client.sendString(_message)
|
||||||
|
|
||||||
|
def send_config(self):
|
||||||
|
serialized = pickle.dumps(self._config['SYSTEMS'], protocol=pickle.HIGHEST_PROTOCOL)
|
||||||
|
self.send_clients(REPORT_OPCODES['CONFIG_SND']+serialized)
|
||||||
|
|
||||||
|
|
||||||
#************************************************
|
#************************************************
|
||||||
# MAIN PROGRAM LOOP STARTS HERE
|
# MAIN PROGRAM LOOP STARTS HERE
|
||||||
|
@ -514,6 +584,9 @@ if __name__ == '__main__':
|
||||||
# Set signal handers so that we can gracefully exit if need be
|
# Set signal handers so that we can gracefully exit if need be
|
||||||
for sig in [signal.SIGTERM, signal.SIGINT]:
|
for sig in [signal.SIGTERM, signal.SIGINT]:
|
||||||
signal.signal(sig, sig_handler)
|
signal.signal(sig, sig_handler)
|
||||||
|
|
||||||
|
# INITIALIZE THE REPORTING LOOP
|
||||||
|
config_reports(CONFIG, logger, reportFactory)
|
||||||
|
|
||||||
# HBlink instance creation
|
# HBlink instance creation
|
||||||
logger.info('HBlink \'HBlink.py\' (c) 2016 N0MJS & the K0USY Group - SYSTEM STARTING...')
|
logger.info('HBlink \'HBlink.py\' (c) 2016 N0MJS & the K0USY Group - SYSTEM STARTING...')
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
###############################################################################
|
||||||
|
# Copyright (C) 2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# Opcodes for the network-based reporting protocol
|
||||||
|
|
||||||
|
REPORT_OPCODES = {
|
||||||
|
'CONFIG_REQ': '\x00',
|
||||||
|
'CONFIG_SND': '\x01',
|
||||||
|
'BRIDGE_REQ': '\x02',
|
||||||
|
'BRIDGE_SND': '\x03',
|
||||||
|
'CONFIG_UPD': '\x04',
|
||||||
|
'BRIDGE_UPD': '\x05',
|
||||||
|
'LINK_EVENT': '\x06',
|
||||||
|
'BRDG_EVENT': '\x07',
|
||||||
|
}
|
Loading…
Reference in New Issue