Commit f8aa6713 authored by Elena Grandi's avatar Elena Grandi

Non working DHCP leases data source

parent b05cc6eb
......@@ -12,6 +12,7 @@ DEFAULTS = {
"web_port": 1232,
"arpwatch_datadir": "/var/lib/arpwatch/",
"dhcp_log_file": "/var/log/syslog",
"dhcp_leases_file": "/var/lib/dhcp/dhcpd.leases",
"debug": False,
"operation_log_file": "/var/log/fuss-manager/operations.log",
"event_log_file": None,
......
......@@ -2,10 +2,12 @@ from .base import DataSource
from .arpwatch import ArpwatchDataSource
from .dhcp import DhcpdDataSource
from .chaos import ChaosDataSource
from .dhcp_leases import DhcpLeasesDataSource
__all__ = (
"DataSource",
"ArpwatchDataSource",
"DhcpdDataSource",
"ChaosDataSource",
"DhcpLeasesDataSource",
)
import asyncio
import logging
import os
import isc_dhcp_leases
from .base import DataSource, MachineDataSourceMixin
from .. import events, compat
from .inotifywait import Inotifywait
class DhcpLeasesDataSource(MachineDataSourceMixin, DataSource):
"""
"""
def __init__(self, config=None, datafile=None, **kw):
super().__init__(**kw)
if datafile:
self.fname = datafile
else:
self.fname = config.dhcp_leases_file
self.watch = Inotifywait(self.fname)
loop = asyncio.get_event_loop()
self.started = compat.create_future(loop)
async def shutdown(self):
self.watch.stop()
async def wait_until_started(self):
await self.started
async def read_events(self):
while True:
event = await self.watch.next_event()
if event == "MODIFIED":
await self.parse_file()
elif event == "END":
break
elif event == "START":
self.started.set_result(True)
await self.event_hub.publish(events.DataSourceStartEvent(self))
await self.event_hub.publish(events.DataSourceStopEvent(self))
async def run(self):
await asyncio.gather(
self.watch.run(), self.read_events(),
)
@classmethod
def is_viable(cls, config, datafile=None):
datafile = datafile or config.dhcp_leases_file
if not super().is_viable(config):
return False
if not os.path.isfile(datafile):
return False
return Inotifywait.is_viable(config)
async def parse_file(self):
leases = isc_dhcp_leases.IscDhcpLeases(self.fname)
for l in leases.get_current():
# do things with the lease
mac = getattr(l, l.hardware, None)
if not mac:
continue
ip = getattr(l, 'ip', None)
await self.event_hub.publish(
events.HostSeenEvent(
mac = mac,
ip = ip,
)
)
......@@ -49,12 +49,15 @@ class Inotifywait:
# mv file.tmp file
# We need to watch the whole directory for "CLOSE_WRITE" and "MOVED_TO"
# with the right file name.
# MODIFY is required for files that are modified in the regular
# way, instead.
self.log.debug("monitoring %s in %s", self.basename, self.dirname)
self.proc = await asyncio.create_subprocess_exec(
self.path_inotifywait,
'-m',
'-e', 'CLOSE_WRITE',
"-e", "MOVED_TO",
"-e", "MODIFY",
"--format", "%e %f",
self.dirname,
stdout=asyncio.subprocess.PIPE,
......
......@@ -16,6 +16,7 @@ setup(
'tornado',
'ruamel.yaml',
'aiodns',
'isc_dhcp_leases',
],
test_suite='nose2.discover',
test_requires=[
......@@ -24,6 +25,7 @@ setup(
'tornado',
'ruamel.yaml',
'aiodns',
'isc_dhcp_leases',
],
classifiers=[
'Framework :: Twisted',
......
import asyncio
import datetime
import tempfile
import shutil
from tornado.testing import gen_test, AsyncTestCase
import manager.sources as ds
from manager import compat
from manager.config import Config
from manager.events import HostSeenEvent
from .common import TestDataSourceMixin, StopTest, GatherEvents
class TestDhcpdLeasesDataSource(TestDataSourceMixin, AsyncTestCase):
"""
test a data source that reads /var/lib/dhcp/dhcpd.leases as it changes
"""
def make_datasource(self):
config = Config()
config.dhcp_leases_file = self.tmpfile.name
return ds.DhcpLeasesDataSource(
event_hub=self.event_hub,
config=config,
)
def setUp(self, *args, **kw):
self.tmpfile = tempfile.NamedTemporaryFile()
super().setUp(*args, **kw)
def tearDown(self, *args, **kw):
self.tmpfile.close()
super().tearDown(*args, **kw)
@gen_test
async def test_command_run(self):
events = GatherEvents(self.event_hub, [HostSeenEvent])
async def test():
await self.ds.wait_until_started()
# some valid dhcp data for one client
with open('tests/data/dhcp_leases.txt', 'rb') as fp:
shutil.copyfileobj(fp, self.tmpfile)
self.tmpfile.flush()
# Wait until changes start to be reported
await events.received_first
await self.event_hub.publish(StopTest(None))
await asyncio.gather(
compat.create_task(self.ds.run()),
compat.create_task(test()),
)
events = events.gathered
self.assertEqual(len(events), 1)
# Full checks on the 3 events for the first machine
self.assertEqual(events[0].name, cliente.school.lan)
self.assertEqual(events[0].mac, "52:54:00:f2:f7:62")
self.assertEqual(events[0].ip, "192.168.6.100")
ts = datetime.datetime.fromtimestamp(events[0].timestamp)
self.assertEqual(
ts,
datetime.datetime(2020,8,20,10,20,2)
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment