123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- from __future__ import print_function
- import io
- import json
- import subprocess
- import time
- from .exceptions import SanityCheckError
- class AlfredParser:
- alfred_json = 'alfred-json'
- alfred_datatypes = [('static', 158), ('dynamic', 159)]
- def __str__(self):
- types = ['{1}=>{0}'.format(x[0], x[1]) for x in self.alfred_datatypes]
- return 'AlfredParser \'{0}\' {1}'.format(
- self.alfred_json,
- str.join(' ', types),
- )
- def sanitycheck(self):
- """
- Checks that the necessary tool 'alfred-json' is callable
- and outputs syntactically correct JSON data.
- """
- testdata = None
- try:
- first_datatype = int(self.alfred_datatypes[0][1])
- cmd = [self.alfred_json, '-z', '-r', str(first_datatype)]
- testdata = subprocess.check_output(cmd)
- except Exception as err:
- raise SanityCheckError(
- self, "alfred-json not found or incompatible", err)
- try:
- json.loads(testdata)
- except Exception as err:
- raise SanityCheckError(
- self, "alfred-json does not return valid JSON data", err)
- return True
- def fetch(self, alfred_dump=None):
- """Fetches the current data from alfred-json."""
- data = {}
- timestamp = int(time.time())
- alfreddata = {}
- for datatype in self.alfred_datatypes:
- # call 'alfred-json' and fetch the output
- cmd = [self.alfred_json, '-z', '-r', str(int(datatype[1]))]
- rawdata = subprocess.check_output(cmd)
- # convert raw input into unicode
- rawdata = unicode(rawdata, encoding='latin1', errors='replace')
- # parse it as JSON
- newdata = json.loads(rawdata)
- for item in newdata:
- if not item in alfreddata:
- alfreddata[item] = {}
- alfreddata[item][datatype[0]] = newdata[item]
- if alfred_dump is not None:
- jsondata = json.dumps(alfreddata, ensure_ascii=False)
- dumpfile = io.open(alfred_dump, 'w')
- dumpfile.write(jsondata)
- dumpfile.close()
- for alfredid in alfreddata:
- alfredinfo = alfreddata[alfredid]
- if 'node_id' in alfredinfo['static']:
- myid = alfredinfo['static']['node_id']
- else:
- myid = alfredid.lower().replace(':', '')
- nodeinfo = {
- 'hostname': None,
- 'mac': None,
- 'software': {},
- 'statistics': {},
- '__UPDATED__': {'alfred': timestamp},
- '__RAW__': {'alfred': alfredinfo},
- }
- data[myid] = nodeinfo
- nodestatic = alfredinfo['static']
- if 'hostname' in nodestatic:
- nodeinfo['hostname'] = nodestatic['hostname']
- if 'network' in nodestatic:
- if 'mac' in nodestatic['network']:
- nodeinfo['mac'] = nodestatic['network']['mac']
- if 'mesh_interfaces' in nodestatic['network']:
- macs = [x for x in nodestatic['network']['mesh_interfaces']]
- nodeinfo['macs'] = macs
- else:
- nodeinfo['macs'] = []
- if 'hardware' in nodestatic:
- hardware = nodestatic['hardware']
- nodeinfo['hardware'] = hardware.get('model')
- if 'software' in nodestatic:
- software = nodestatic['software']
- nodeinfo['software']['firmware'] = \
- software.get('firmware', {}).get('release')
- autoupdater = software.get('autoupdater', {})
- autoupdater_enabled = autoupdater.get('enabled', False)
- nodeinfo['software']['autoupdater'] = \
- autoupdater.get('branch') if autoupdater_enabled else 'off'
- nodedyn = alfredinfo.get('dynamic',
- nodestatic.get('statistics', {}))
- if 'uptime' in nodedyn:
- nodeinfo['uptime'] = int(float(nodedyn['uptime']))
- if 'gateway' in nodedyn:
- nodeinfo['gateway'] = nodedyn['gateway']
- traffic = nodedyn["traffic"] if "traffic" in nodedyn else None
- if traffic is not None:
- if not 'traffic' in nodeinfo['statistics']:
- nodeinfo['statistics']['traffic'] = {}
- item = nodeinfo['statistics']['traffic']
- item['rxbytes'] = int(traffic["rx"]["bytes"])
- item['txbytes'] = int(traffic["tx"]["bytes"])
- if 'location' in nodestatic:
- nodeinfo['location'] = nodestatic['location']
- return data
- if __name__ == "__main__":
- parser = AlfredParser()
- try:
- parser.sanitycheck()
- except SanityCheckError as err:
- print('SANITY-CHECK failed:', str(err))
- import sys
- sys.exit(1)
- adata = parser.fetch()
- print(json.dumps(adata))
|