Cleanup and support Environment config

This commit is contained in:
2020-05-04 10:28:36 +01:00
parent 193ab5fb57
commit fc3552eb07
2 changed files with 105 additions and 73 deletions

View File

@@ -1,133 +1,164 @@
#!/usr/bin/env python #!/usr/bin/env python
import os
import sys import sys
import logging import logging
import json import json
import urllib
import time import time
import configparser import configparser
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
import humanfriendly import humanfriendly
import requests
import argparse
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
VERSION = 0.1 VERSION = 0.2
AAISP_INFO_URL = 'https://chaos2.aa.net.uk/broadband/info'
def main(): def main():
logging.basicConfig(level=logging.INFO, format='%(levelname)8s [%(asctime)s] %(message)s') logging.basicConfig(level=logging.INFO,
format='%(levelname)8s [%(asctime)s] %(message)s')
if len(sys.argv) != 2: if len(sys.argv) > 1:
LOG.fatal("Config file not supplied")
sys.exit(1)
cfgfile = sys.argv[1] cfgfile = sys.argv[1]
# load the config # load the config
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read(cfgfile) config.read(cfgfile)
# check it has the correct sections # check it has the correct sections
for section in ["aaisp", "mqtt"]: for section in ['aaisp', 'mqtt']:
if section not in config.sections(): if section not in config.sections():
LOG.fatal("%s section not found in config file %s", section, cfgfile) LOG.fatal('%s section not found in config file %s',
section, cfgfile)
aaisp_username = config.get("aaisp", "username") aaisp_username = config.get('aaisp', 'username')
aaisp_password = config.get("aaisp", "password") aaisp_password = config.get('aaisp', 'password')
mqtt_broker = config.get('mqtt', 'broker')
mqtt_port = int(config.get('mqtt', 'port', fallback='1883'))
mqtt_username = config.get('mqtt', 'username', fallback=None)
mqtt_password = config.get('mqtt', 'password', fallback=None)
mqtt_topic_prefix = config.get('mqtt', 'topic_prefix', fallback='aaisp')
else:
# Use the environment
aaisp_username = os.environ.get('AAISP_USERNAME')
aaisp_password = os.environ.get('AAISP_PASSWORD')
mqtt_broker = os.environ.get('MQTT_BROKER') or 'localhost'
mqtt_port = int(os.environ.get('MQTT_PORT') or '1883')
mqtt_username = os.environ.get('MQTT_USERNAME')
mqtt_password = os.environ.get('MQTT_PASSWORD')
mqtt_topic_prefix = os.environ.get('MQTT_TOPIC_PREFIX') or 'aaisp'
if aaisp_username is None or aaisp_password is None:
LOG.fatal('Username or Password missing for AAISP')
sys.exit(1)
# attempt to get details from aaisp # attempt to get details from aaisp
LOG.info("Connecting to AAISP CHAOSv2 endpoint") LOG.info('Connecting to AAISP CHAOSv2 endpoint')
post_params = "control_login=%s&control_password=%s" % (aaisp_username, aaisp_password) response = requests.get(AAISP_INFO_URL, params={
url = "https://chaos2.aa.net.uk/broadband/info" 'control_login': aaisp_username,
response = urllib.urlopen(url, data=post_params) 'control_password': aaisp_password
data = json.loads(response.read()) })
if "info" not in data: if not response.status_code == requests.codes.ok:
LOG.fatal("info section not found in AAISP CHAOSv2 response") LOG.error('Error connecting to AAISP CHAOSv2 endpoint: %s' % response.body)
sys.exit(1) sys.exit(1)
circuits = data["info"] data = response.json()
LOG.info("Got %s circuits", len(circuits))
if 'info' not in data:
LOG.fatal('info section not found in AAISP CHAOSv2 response')
sys.exit(1)
circuits = data['info']
LOG.info('Got %s circuits', len(circuits))
if len(circuits) == 0: if len(circuits) == 0:
LOG.fatal("No circuits returned from AAISP CHAOSv2") LOG.fatal('No circuits returned from AAISP CHAOSv2')
# work out unique line IDs and logins # work out unique line IDs and logins
logins = [] logins = []
lines = [] lines = []
for circuit in circuits: for circuit in circuits:
if circuit["login"] not in logins: if circuit['login'] not in logins:
logins.append(circuit["login"]) logins.append(circuit['login'])
if circuit["ID"] not in lines: if circuit['ID'] not in lines:
lines.append(circuit["ID"]) lines.append(circuit['ID'])
LOG.info("* Lines: %s", ', '.join(lines)) LOG.info('* Lines: %s', ', '.join(lines))
LOG.info("* Logins: %s", ', '.join(logins)) LOG.info('* Logins: %s', ', '.join(logins))
# get MQTT config
mqtt_broker = config.get("mqtt", "broker")
mqtt_port = int(config.get("mqtt", "port"))
mqtt_username = config.get("mqtt", "username")
mqtt_password = config.get("mqtt", "password")
mqtt_topic_prefix = config.get("mqtt", "topic_prefix")
# connect to the broker # connect to the broker
LOG.info("Connecting to MQTT broker %s:%s", mqtt_broker, mqtt_port) LOG.info('Connecting to MQTT broker %s:%s', mqtt_broker, mqtt_port)
client = mqtt.Client() client = mqtt.Client()
# do auth? # do auth?
if mqtt_username is not None and mqtt_password is not None: if mqtt_username is not None and mqtt_password is not None:
client.username_pw_set(mqtt_username, mqtt_password) client.username_pw_set(mqtt_username, mqtt_password)
client.max_inflight_messages_set(100) client.max_inflight_messages_set(100)
try:
client.connect(mqtt_broker, mqtt_port, 60) client.connect(mqtt_broker, mqtt_port, 60)
LOG.info("Connected OK to MQTT") except Exception:
LOG.exception('Error connecting to MQTT')
sys.exit(1)
LOG.info('Connected OK to MQTT')
# version and indexes # version and indexes
publish(client=client, topic="%s/$version" % (mqtt_topic_prefix), payload=VERSION) publish(client=client, topic='%s/$version' %
publish(client=client, topic="%s/$lines" % (mqtt_topic_prefix), payload=','.join(lines)) (mqtt_topic_prefix), payload=VERSION)
publish(client=client, topic="%s/$logins" % (mqtt_topic_prefix), payload=','.join(logins)) publish(client=client, topic='%s/$lines' %
LOG.info("Published version and index messages") (mqtt_topic_prefix), payload=','.join(lines))
publish(client=client, topic='%s/$logins' %
(mqtt_topic_prefix), payload=','.join(logins))
LOG.info('Published version and index messages')
# publish per circuit # publish per circuit
for circuit in circuits: for circuit in circuits:
publish_per_circuit(client=client, circuit=circuit, mqtt_topic_prefix=mqtt_topic_prefix) publish_per_circuit(client=client, circuit=circuit,
LOG.info("Published details for %s circuits", len(circuits)) mqtt_topic_prefix=mqtt_topic_prefix)
LOG.info('Published details for %s circuits', len(circuits))
# disconnect # disconnect
LOG.info("Disconnecting from MQTT") LOG.info('Disconnecting from MQTT')
client.disconnect() client.disconnect()
sys.exit(0) sys.exit(0)
def publish_per_circuit(client, circuit, mqtt_topic_prefix): def publish_per_circuit(client, circuit, mqtt_topic_prefix):
quota_remaining = int(circuit["quota_remaining"]) quota_remaining = int(circuit['quota_remaining'])
quota_remaining_gb = quota_remaining / 1000000000 quota_remaining_gb = quota_remaining / 1000000000
quota_monthly = int(circuit["quota_monthly"]) quota_monthly = int(circuit['quota_monthly'])
quota_monthly_gb = quota_monthly / 1000000000 quota_monthly_gb = quota_monthly / 1000000000
up = float(circuit["rx_rate"]) up = float(circuit['rx_rate'])
up_mb = round(up / 1000000, 2) up_mb = round(up / 1000000, 2)
down = float(circuit["tx_rate"]) down = float(circuit['tx_rate'])
down_mb = round(down / 1000000, 2) down_mb = round(down / 1000000, 2)
# line_prefix = "%s/line/%s" % (mqtt_topic_prefix, circuit["ID"]) # line_prefix = '%s/line/%s' % (mqtt_topic_prefix, circuit['ID'])
login_prefix = "%s/login/%s" % (mqtt_topic_prefix, circuit["login"]) login_prefix = '%s/login/%s' % (mqtt_topic_prefix, circuit['login'])
for prefix in [login_prefix]: # , line_prefix]: for prefix in [login_prefix]: # , line_prefix]:
for metric in [ for metric in [
("quota/remaining", quota_remaining), ('quota/remaining', quota_remaining),
("quota/remaining/gb", quota_remaining_gb), ('quota/remaining/gb', quota_remaining_gb),
("quota/remaining/human", humanfriendly.format_size(quota_remaining)), ('quota/remaining/human', humanfriendly.format_size(quota_remaining)),
("quota/monthly", quota_monthly), ('quota/monthly', quota_monthly),
("quota/monthly/gb", quota_monthly_gb), ('quota/monthly/gb', quota_monthly_gb),
("quota/monthly/human", humanfriendly.format_size(quota_monthly)), ('quota/monthly/human', humanfriendly.format_size(quota_monthly)),
("syncrate/up", up), ('syncrate/up', up),
("syncrate/up/mb", up_mb), ('syncrate/up/mb', up_mb),
("syncrate/up/human", humanfriendly.format_size(up)), ('syncrate/up/human', humanfriendly.format_size(up)),
("syncrate/down", down), ('syncrate/down', down),
("syncrate/down/mb", down_mb), ('syncrate/down/mb', down_mb),
("syncrate/down/human", humanfriendly.format_size(down)), ('syncrate/down/human', humanfriendly.format_size(down)),
("postcode", str(circuit["postcode"].strip())) ('postcode', str(circuit['postcode'].strip()))
]: ]:
topic = "%s/%s" % (prefix, metric[0]) topic = '%s/%s' % (prefix, metric[0])
publish(client=client, topic=topic, payload=metric[1]) publish(client=client, topic=topic, payload=metric[1])
return return
def publish(client, topic, payload): def publish(client, topic, payload):
time.sleep(0.1) time.sleep(0.1)
result = client.publish(topic=topic, payload=payload, qos=1) result = client.publish(topic=topic, payload=payload, qos=1)
if result[0] != 0: if result[0] != 0:
LOG.fail("MQTT publish failure: %s %s" , topic, payload) LOG.fail('MQTT publish failure: %s %s', topic, payload)
if __name__ == "__main__":
if __name__ == '__main__':
main() main()

View File

@@ -1,3 +1,4 @@
paho-mqtt>=1.2 paho-mqtt>=1.2
configparser>=3.5.0 configparser>=3.5.0
humanfriendly>=2.1 humanfriendly>=2.1
requests>=2.23.0