MAC address matching and stuff.

This commit is contained in:
q3k 2012-11-14 15:10:39 +01:00
parent a3bba233cd
commit eb1f6b64cb
4 changed files with 95 additions and 53 deletions

29
hooks.py Normal file
View file

@ -0,0 +1,29 @@
import cStringIO
import time
from khepri import hook, get_mac
@hook(r"^pxelinux.cfg/default$")
def pxelinux_default(path, match, remote):
(raddress, rport) = remote
mac = get_mac(raddress)
if not mac:
s = "localboot 0"
else:
s = """ default menu.c32
prompt 0
menu title "Khepri Boot Menu generated at %s for %s:%i"
menu INCLUDE pxelinux.cfg/graphics.conf
MENU AUTOBOOT Starting Xen Node in # seconds
label xen
menu label ^Xen Node
menu default
timeout 80
kernel xen/vmlinuz
append rootfstype=nfs root=/dev/nfs nfsroot=10.8.1.1:/var/khepri/nfs/xen,v4,rsize=16384,wsize=16384 ip=:::::eth0:dhcp
""" % (time.strftime("%d/%m/%Y at %H:%M:%S"), raddress, rport)
return cStringIO.StringIO(s)

62
khepri.py Executable file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env python
import sys, logging
import tftpy
import re
LEASES_FILE = "/var/lib/dhcp/dhcpd.leases"
def get_mac(address):
"""Gets MAC address from dhcpd leases based on IP address."""
f = open(LEASES_FILE,"r")
in_lease = False
for line in f:
line = line.split("#")[0]
parts = line.strip().split()
if not parts:
continue
if not in_lease and parts[0] == "lease":
in_lease = parts[1]
continue
field_name = parts[0]
if field_name == "hardware" and in_lease == address:
return parts[2][:-1]
elif field_name == "}":
in_lease = False
return None
file_hooks = {}
def hook_dispatcher(path, remote):
for pattern, hook in file_hooks.iteritems():
match = re.match(pattern, path)
if match:
data = hook(path, match, remote)
if data:
return data
return None
def hook(pattern, match_mac=None):
def decorator(f):
def wrapper(path, match, remote):
if match_mac:
mac = get_mac([0])
if match_mac and mac != match_mac:
return None
return f(path, match, remote)
file_hooks[pattern] = wrapper
return f
return decorator
import hooks
def main():
server = tftpy.TftpServer("/var/khepri/tftp-root/", dyn_file_func=hook_dispatcher)
try:
server.listen("10.8.1.1", 5000)
except tftpy.TftpException, err:
sys.stderr.write("%s\n" % str(err))
sys.exit(1)
except KeyboardInterrupt:
pass

55
run.py Executable file → Normal file
View file

@ -1,53 +1,4 @@
#!/usr/bin/env python
import khepri
import sys, logging
import tftpy
import re
import cStringIO
import time
file_hooks = {}
def hook_dispatcher(path):
for pattern, hook in file_hooks.iteritems():
match = re.match(pattern, path)
if match:
return hook(path, match)
return None
def hook(pattern):
def decorator(f):
file_hooks[pattern] = f
return f
return decorator
@hook(r"^pxelinux.cfg/default$")
def pxelinux_default(path, match):
s = """default menu.c32
prompt 0
menu title "Khepri Boot Menu generated at %s"
menu INCLUDE pxelinux.cfg/graphics.conf
MENU AUTOBOOT Starting Xen Node in # seconds
label xen
menu label ^Xen Node
menu default
timeout 80
kernel xen/vmlinuz
append rootfstype=nfs root=/dev/nfs nfsroot=10.8.1.1:/var/khepri/nfs/xen,v4,rsize=16384,wsize=16384 ip=:::::eth0:dhcp
""" % time.strftime("%d/%m/%Y at %H:%M:%S")
return cStringIO.StringIO(s)
def main():
server = tftpy.TftpServer("/var/khepri/tftp-root/", dyn_file_func=hook_dispatcher)
try:
server.listen("10.8.1.1", 5000)
except tftpy.TftpException, err:
sys.stderr.write("%s\n" % str(err))
sys.exit(1)
except KeyboardInterrupt:
pass
if __name__ == '__main__':
main()
if __name__ == "__main__":
khepri.main()

View file

@ -285,7 +285,7 @@ class TftpStateServerRecvRRQ(TftpServerState):
elif self.context.dyn_file_func:
log.debug("No such file %s but using dyn_file_func" % path)
self.context.fileobj = \
self.context.dyn_file_func(self.context.file_to_transfer)
self.context.dyn_file_func(self.context.file_to_transfer, (raddress, rport))
if self.context.fileobj is None:
log.debug("dyn_file_func returned 'None', treating as "