annotate service/dhcpleases/dhcpleases.py @ 722:a93fbf0d0daa

dep updates; graph url renames; and other build updates Ignore-this: 4603ef3d8db650a13e543dad8580ade8
author drewp@bigasterisk.com
date Wed, 05 Feb 2020 00:23:06 -0800
parents f372e9d358d2
children b87b6e9cedb2
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
1 """
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
2 statements about dhcp leases (and maybe live-host pings)
480
53ceedcc2809 dhcpleases partial rewrite
drewp@bigasterisk.com
parents: 203
diff changeset
3
53ceedcc2809 dhcpleases partial rewrite
drewp@bigasterisk.com
parents: 203
diff changeset
4 also read 'arp -an' and our dns list
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
5 """
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
6 import datetime, itertools, os
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
7
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
8 from docopt import docopt
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
9 from dateutil.tz import tzlocal
480
53ceedcc2809 dhcpleases partial rewrite
drewp@bigasterisk.com
parents: 203
diff changeset
10 from rdflib import URIRef, Namespace, Literal, RDF, RDFS, XSD, ConjunctiveGraph
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
11 from twisted.internet import reactor, task
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
12 import cyclone.web
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
13
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
14 from greplin import scales
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
15 from greplin.scales.cyclonehandler import StatsHandler
480
53ceedcc2809 dhcpleases partial rewrite
drewp@bigasterisk.com
parents: 203
diff changeset
16 from patchablegraph import PatchableGraph, CycloneGraphEventsHandler, CycloneGraphHandler
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
17 from standardservice.logsetup import log, verboseLogging
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
18
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
19 DEV = Namespace("http://projects.bigasterisk.com/device/")
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
20 ROOM = Namespace("http://projects.bigasterisk.com/room/")
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
21 ctx = DEV['dhcp']
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
22
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
23 STATS = scales.collection('/root',
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
24 scales.PmfStat('readLeases'),
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
25 scales.IntStat('filesDidntChange'),
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
26 )
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
27
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
28 def timeLiteral(dt):
162
bb70eaa45666 whitespace
drewp@bigasterisk.com
parents: 161
diff changeset
29 return Literal(dt.replace(tzinfo=tzlocal()).isoformat(),
bb70eaa45666 whitespace
drewp@bigasterisk.com
parents: 161
diff changeset
30 datatype=XSD.dateTime)
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
31
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
32 def macUri(macAddress: str) -> URIRef:
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
33 return URIRef("http://bigasterisk.com/mac/%s" % macAddress.lower())
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
34
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
35 class Poller:
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
36 def __init__(self, graph):
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
37 self.graph = graph
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
38 self.fileTimes = {'/opt/dnsmasq/10.1/leases': 0, '/opt/dnsmasq/10.2/leases': 0}
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
39 task.LoopingCall(self.poll).start(2)
480
53ceedcc2809 dhcpleases partial rewrite
drewp@bigasterisk.com
parents: 203
diff changeset
40
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
41 def anythingToRead(self):
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
42 ret = False
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
43 for f, t in self.fileTimes.items():
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
44 mtime = os.path.getmtime(f)
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
45 if mtime > t:
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
46 self.fileTimes[f] = mtime
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
47 ret = True
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
48 return ret
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
49
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
50 def poll(self):
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
51 if not self.anythingToRead():
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
52 STATS.filesDidntChange += 1
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
53 return
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
54
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
55 with STATS.readLeases.time():
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
56 g = ConjunctiveGraph()
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
57 for line in itertools.chain(*[open(f) for f in self.fileTimes]):
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
58 # http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2016q2/010595.html
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
59 expiration_secs, addr, ip, hostname, clientid = line.strip().split(' ')
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
60
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
61 uri = macUri(addr)
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
62 g.add((uri, RDF.type, ROOM['HasDhcpLease'], ctx))
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
63 g.add((uri, ROOM['macAddress'], Literal(addr), ctx))
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
64 g.add((uri, ROOM['assignedIp'], Literal(ip), ctx))
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
65
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
66 if hostname != '*':
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
67 g.add((uri, ROOM['dhcpHostname'], Literal(hostname), ctx))
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
68
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
69 self.graph.setToGraph(g)
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
70
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
71 if __name__ == '__main__':
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
72 arg = docopt("""
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
73 Usage: store.py [options]
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
74
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
75 -v Verbose
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
76 --port PORT Serve on port [default: 9073].
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
77 """)
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
78
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
79 verboseLogging(arg['-v'])
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
80
480
53ceedcc2809 dhcpleases partial rewrite
drewp@bigasterisk.com
parents: 203
diff changeset
81 masterGraph = PatchableGraph()
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
82 poller = Poller(masterGraph)
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
83
174
ab98f8d72be0 new index page. fix dhcp scanner errors
drewp@bigasterisk.com
parents: 162
diff changeset
84 reactor.listenTCP(
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
85 int(arg['--port']),
174
ab98f8d72be0 new index page. fix dhcp scanner errors
drewp@bigasterisk.com
parents: 162
diff changeset
86 cyclone.web.Application(
ab98f8d72be0 new index page. fix dhcp scanner errors
drewp@bigasterisk.com
parents: 162
diff changeset
87 [
ab98f8d72be0 new index page. fix dhcp scanner errors
drewp@bigasterisk.com
parents: 162
diff changeset
88 (r"/()", cyclone.web.StaticFileHandler,
ab98f8d72be0 new index page. fix dhcp scanner errors
drewp@bigasterisk.com
parents: 162
diff changeset
89 {"path": ".", "default_filename": "index.html"}),
722
a93fbf0d0daa dep updates; graph url renames; and other build updates
drewp@bigasterisk.com
parents: 531
diff changeset
90 (r'/graph/dhcpLeases', CycloneGraphHandler, {'masterGraph': masterGraph}),
a93fbf0d0daa dep updates; graph url renames; and other build updates
drewp@bigasterisk.com
parents: 531
diff changeset
91 (r'/graph/dhcpLeases/events', CycloneGraphEventsHandler, {'masterGraph': masterGraph}),
531
f372e9d358d2 rewrite dhcpleases to use dnsmasq's data files, and all the new build stuff
drewp@bigasterisk.com
parents: 480
diff changeset
92 (r'/stats/(.*)', StatsHandler, {'serverName': 'dhcpleases'}),
480
53ceedcc2809 dhcpleases partial rewrite
drewp@bigasterisk.com
parents: 203
diff changeset
93 ], masterGraph=masterGraph
174
ab98f8d72be0 new index page. fix dhcp scanner errors
drewp@bigasterisk.com
parents: 162
diff changeset
94 ))
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents:
diff changeset
95 reactor.run()