From 705e7a60d914aefb59d7d72f476daec63fc2712d Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Thu, 14 Aug 2008 13:33:41 +0200
Subject: [PATCH] Version 2008-08-14 13:33

M  src/hostinfo.py
M  src/hostinfo/dhcpd.py
M  src/hostinfo/ifconfig.py
A  src/hostinfo/pxelinux.py
---
 src/hostinfo.py          | 20 +++++++++--
 src/hostinfo/dhcpd.py    | 72 +++++++++++++++++++++++++---------------
 src/hostinfo/ifconfig.py | 43 ++++++++++++++++++++++++
 src/hostinfo/pxelinux.py | 11 ++++++
 4 files changed, 117 insertions(+), 29 deletions(-)
 create mode 100755 src/hostinfo/pxelinux.py

diff --git a/src/hostinfo.py b/src/hostinfo.py
index e75dde0..731d10b 100755
--- a/src/hostinfo.py
+++ b/src/hostinfo.py
@@ -7,6 +7,7 @@ import hostinfo.macosx_auto
 import hostinfo.mio
 import hostinfo.named
 import hostinfo.parser
+import hostinfo.pxelinux
 import hostinfo.samba
 import hostinfo.yp
 import optparse
@@ -179,6 +180,9 @@ if __name__ == '__main__':
     optParser.add_option("--ifconfig",
                          action="store", metavar="DIR",
                          help="Generate DIR/ifcfg-eth*")
+    optParser.add_option("--kickstart",
+                         action="store",  metavar="DIR",
+                         help="kickstart files should be fetched from DIR")
     optParser.add_option("--macosx_auto",
                          action="store", metavar="DIR",
                          help="Generate MacOSX autmount maps")
@@ -191,6 +195,9 @@ if __name__ == '__main__':
     optParser.add_option("--pretty",
                          action="store_true", default=False, 
                          help="pretty-print XML tree")
+    optParser.add_option("--pxelinux",
+                         action="store",  metavar="DIR", 
+                         help="symlink DIR/<ethernet> to <kickstart>")
     optParser.add_option("--samba",
                          action="store",  metavar="FILE",
                          help="generate samba share FILE")
@@ -217,7 +224,12 @@ if __name__ == '__main__':
             symlink["%s/%s" % (options.dfs, f)] = c
 
     if options.dhcpd:
-        file["%s/dhcpd.conf" % options.dhcpd] = hostinfo.dhcpd.conf(tree, host)
+        name = "%s/dhcpd.conf" % options.dhcpd
+        if options.kickstart:
+            kickstart = os.path.abspath(options.kickstart)
+        else:
+            kickstart = None
+        file[name] = hostinfo.dhcpd.conf(tree, host, kickstart)
     
     if options.ifconfig:
         for (f, c) in hostinfo.ifconfig.generate(tree, host):
@@ -235,6 +247,10 @@ if __name__ == '__main__':
         for (f, c) in hostinfo.named.generate(tree, host):
             file["%s/%s" % (options.named, f)] = c
 
+    if options.pxelinux:
+        for (f, c) in hostinfo.pxelinux.generate(tree, host):
+            symlink["%s/%s" % (options.pxelinux, f)] = c
+            
     if options.pretty:
         result = "<?xml version='1.0' encoding='iso8859-1'?>\n\n"
         result += tree._xml(attr_sort=attr_sort, tag_sort=tag_sort)
@@ -268,7 +284,7 @@ if __name__ == '__main__':
 
     for name in symlink.keys():
         if os.path.lexists(name) and not os.path.islink(name):
-            print "'%s' esists but is not a link"
+            print "'%s' exists but is not a link" % name
         elif not os.path.lexists(name):
             print "Creating '%s' -> '%s'" % (name, symlink[name])
             os.symlink(symlink[name], name)
diff --git a/src/hostinfo/dhcpd.py b/src/hostinfo/dhcpd.py
index c255d7d..d0878cb 100755
--- a/src/hostinfo/dhcpd.py
+++ b/src/hostinfo/dhcpd.py
@@ -46,7 +46,7 @@ class "AppleNBI-ppc" {
 
 """ % (dhcphost, dhcphost)
     
-def conf(tree, dhcphost):
+def conf(tree, dhcphost, kickstart):
     #
     # A. Get interfaces to serve
     #
@@ -71,39 +71,47 @@ def conf(tree, dhcphost):
     #
     for i in interface:
         address = []
+        vlan = []
         if i.ip[0]:
             # Main address
             address.append(i.ip[0])
         for ip in i._ip_:
-            # Alias addresses
-            if ip.address[0]:
+            if ip.alias[0] and ip.address[0]:
+                # Alias addresses
                 address.append(ip.address[0])
+            elif ip.vlan[0] and ip.address[0]:
+                vlan.append(ip.address[0])
+                
+        result += emit_network(tree, dhcphost, address, kickstart,
+                               i.ethernet[0])
+        for v in vlan:
+            result += emit_network(tree, dhcphost, [ v ], kickstart)
 
-        # Collect subnets for this interface
-        network = {}
-        for n in tree._subnet_:
-            if not n.network[0]:
-                continue
-            netmask = aton(n.netmask[0])
-            subnet = aton(n.network[0]) & netmask
-            for a in address:
-                if aton(a) & netmask == subnet:
-                    network[ntoa(subnet)] = n
-
-        # Emit subnet declarations
-        if len(network.keys()) > 1:
-            # Multiple networks served on this interface
-            result += 'shared-network "MAC(%s)" {\n\n' % i.ethernet[0]
-            for n in network.values():
-                for l in emit_subnet(tree, n, dhcphost).split("\n"):
-                    result += "  %s\n" % l
-            result += "}\n"
-        else:
-            result += emit_subnet(tree, network.values()[0], dhcphost)
-
+    return result
+                    
+def emit_network(tree, dhcphost, addr, kickstart, ethernet=None):
+    result = ""
+    network = {}
+    for n in tree._subnet_:
+        if not n.network[0]:
+            continue
+        netmask = aton(n.netmask[0])
+        subnet = aton(n.network[0]) & netmask
+        for a in addr:
+            if aton(a) & netmask == subnet:
+                network[ntoa(subnet)] = n
+    if len(network.keys()) > 1:
+        # Multiple networks served on this interface
+        result += 'shared-network "MAC(%s)" {\n\n' % ethernet
+        for n in network.values():
+            for l in emit_subnet(tree, n, dhcphost, kickstart).split("\n"):
+                result += "  %s\n" % l
+        result += "}\n"
+    else:
+        result += emit_subnet(tree, network.values()[0], dhcphost, kickstart)
     return result
 
-def emit_subnet(tree, n, dhcphost):
+def emit_subnet(tree, n, dhcphost, kickstart):
     result = ""
 
     netmask = aton(n.netmask[0])
@@ -133,6 +141,8 @@ def emit_subnet(tree, n, dhcphost):
     if n.name_servers[0]:
         result += "  option domain-name-servers %s;\n" % (
             n.name_servers[0])
+    if n.ntp_servers[0]:
+        result += "  option ntp-servers %s;\n" % (n.ntp_servers[0])
 
     #
     # Emit dynamic hosts
@@ -174,10 +184,18 @@ def emit_subnet(tree, n, dhcphost):
             result += "      fixed-address %s;\n" % ip
             result += "      option host-name \"%s\";\n" % i.name[0:]
             if i._kickstart_:
+                if not kickstart:
+                    raise Exception("--kickstart needed for %s" % i.name[0:])
                 kf = i._kickstart_[0].file[0]
                 result += "      server-name \"%s\";\n" % dhcphost
                 result += "      next-server %s;\n" % dhcphost
-                result += "      filename \"/local/kickstart/%s\";\n" % kf
+                result += "      if substring(option vendor-class-identifier, "
+                result += "0, 20) = \n"
+                result += "         \"PXEClient:Arch:00000\" {\n"
+                result += "        filename \"pxelinux.0\";\n"
+                result += "      } else {\n"
+                result += "        filename \"%s/%s\";\n" % (kickstart, kf)
+                result += "      }\n"
             for d in i._dhcp_:
                 result += "      %s\n" % d.value[0]
             result += "    }\n"
diff --git a/src/hostinfo/ifconfig.py b/src/hostinfo/ifconfig.py
index 7809233..4f5d9f8 100755
--- a/src/hostinfo/ifconfig.py
+++ b/src/hostinfo/ifconfig.py
@@ -9,6 +9,7 @@ def generate(tree, host):
             for i in h._interface_:
                 d = device(i.ethernet[0])
                 if d:
+                    # Ordinary ethernet 
                     config = "DEVICE=%s\n" % d
                     config += "HWADDR=%s\n" % i.ethernet[0].upper()
                     config += "ONBOOT=yes\n"
@@ -32,6 +33,48 @@ def generate(tree, host):
                     else:
                         config += "BOOTPROTO=dhcp\n"
                     result.append(("ifcfg-%s" % d, config))
+
+                    # Aliases and VLANs
+                    for ip in i._ip_:
+                        if ip.alias[0]:
+                            name = "%s:%s" % (d, ip.alias[0])
+                            config = "DEVICE=%s\n" % name
+                            config += "HWADDR=%s\n" % i.ethernet[0].upper()
+                            config += "ONPARENT=yes\n"
+                            if not i._dhcpserver_:
+                                config += "BOOTPROTO=dhcp\n"
+                            else:
+                                s = subnet(tree, ip.address[0])
+                                config += "IPADDR=%s\n" % ip.address[0]
+                                if s and s.netmask[0]:
+                                    config += "NETMASK=%s\n" % s.netmask[0]
+                                if s and s.network[0]:
+                                    config += "NETWORK=%s\n" % s.network[0]
+                                if s and s.broadcast[0]:
+                                    config += "BROADCAST=%s\n" % s.broadcast[0]
+
+                            result.append(("ifcfg-%s" % name , config))
+                            
+                        elif ip.vlan[0]:
+                            name = "%s.%s" % (d, ip.vlan[0])
+                            config = "DEVICE=%s\n" % name
+                            config += "HWADDR=%s\n" % i.ethernet[0].upper()
+                            config += "ONBOOT=yes\n"
+                            config += "VLAN=yes\n"
+                            if not i._dhcpserver_:
+                                config += "BOOTPROTO=dhcp\n"
+                            else:
+                                s = subnet(tree, ip.address[0])
+                                config += "IPADDR=%s\n" % ip.address[0]
+                                if s and s.netmask[0]:
+                                    config += "NETMASK=%s\n" % s.netmask[0]
+                                if s and s.network[0]:
+                                    config += "NETWORK=%s\n" % s.network[0]
+                                if s and s.broadcast[0]:
+                                    config += "BROADCAST=%s\n" % s.broadcast[0]
+
+                            result.append(("ifcfg-%s" % name , config))
+                    
     return result
                                 
 
diff --git a/src/hostinfo/pxelinux.py b/src/hostinfo/pxelinux.py
new file mode 100755
index 0000000..80140c7
--- /dev/null
+++ b/src/hostinfo/pxelinux.py
@@ -0,0 +1,11 @@
+import sys
+import os
+from hostinfo.util import ntoa, aton
+
+def generate(tree, dhcphost):
+    result = []
+    for i in tree._host_._interface_:
+        if i.ethernet[0] and i._kickstart_:
+            result.append(("01-" + i.ethernet[0].replace(':', '-'),
+                           i._kickstart_[0].file[0]))
+    return result
-- 
GitLab