summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKen Raffenetti <raffenet@mcs.anl.gov>2006-08-28 18:55:11 +0000
committerKen Raffenetti <raffenet@mcs.anl.gov>2006-08-28 18:55:11 +0000
commite6fcdfd7cf435ccd4826d5aef9f6a6b36cd0b3a1 (patch)
treef81b153d83abf8043da9eff299c06dba8636dfbb /src
parent8ddd63548d2f971751e05f6c0784698453eb53d1 (diff)
downloadbcfg2-e6fcdfd7cf435ccd4826d5aef9f6a6b36cd0b3a1.tar.gz
bcfg2-e6fcdfd7cf435ccd4826d5aef9f6a6b36cd0b3a1.tar.bz2
bcfg2-e6fcdfd7cf435ccd4826d5aef9f6a6b36cd0b3a1.zip
Initial Hostbase stuff
git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@2128 ce84e21b-d406-0410-9b95-82705330c041
Diffstat (limited to 'src')
-rw-r--r--src/lib/Server/Hostbase/views.py653
-rw-r--r--src/lib/Server/Plugins/Hostbase.py680
2 files changed, 1052 insertions, 281 deletions
diff --git a/src/lib/Server/Hostbase/views.py b/src/lib/Server/Hostbase/views.py
new file mode 100644
index 000000000..8f79670e3
--- /dev/null
+++ b/src/lib/Server/Hostbase/views.py
@@ -0,0 +1,653 @@
+"""Views.py
+Contains all the views associated with the dbconvert app
+Also has does form validation
+"""
+__revision__ = 0.1
+
+from django.http import HttpResponse, HttpResponseRedirect
+from models import *
+from Cheetah.Template import Template
+from datetime import date
+from django.db import connection
+import re
+
+attribs = ['hostname', 'whatami', 'netgroup', 'security_class', 'support',
+ 'csi', 'printq', 'primary_user', 'administrator', 'location',
+ 'comments', 'status']
+
+dispatch = {'mac_addr':'i.mac_addr LIKE \'%%%%%s%%%%\'',
+ 'ip_addr':'p.ip_addr LIKE \'%%%%%s%%%%\'',
+ 'name':'n.name LIKE \'%%%%%s%%%%\'',
+ 'cname':'c.cname LIKE \'%%%%%s%%%%\'',
+ 'mx':'m.mx LIKE \'%%%%%s%%%%\'',
+ 'dns_view':'n.dns_view = \'%s\'',
+ 'hdwr_type':'i.hdwr_type = \'%s\''}
+
+
+## def netreg(request):
+## if request.GET.has_key('sub'):
+## failures = []
+## validated = True
+## # do validation right in here
+## macaddr_regex = re.compile('^[0-9abcdef]{2}(:[0-9abcdef]{2}){5}$')
+## if not (request.POST['mac_addr'] and macaddr_regex.match(request.POST['mac_addr'])):
+## validated = False
+## userregex = re.compile('^[a-z0-9-_\.@]+$')
+## if not (request.POST['email_address'] and userregex.match(request.POST['email_address'])):
+## validated = False
+## if not validated:
+## t = Template(open('./dbconvert/templates/errors.html').read())
+## t.failures = validate(request, True)
+## return HttpResponse(str(t))
+## return HttpResponseRedirect('/dbconvert/%s/' % host.id)
+## else:
+## t = Template(open('./dbconvert/templates/netreg.html').read())
+## t.TYPE_CHOICES = Interface.TYPE_CHOICES
+## t.failures = False
+## return HttpResponse(str(t))
+
+
+def search(request):
+ """Search for hosts in the database
+ If more than one field is entered, logical AND is used
+ """
+ if request.GET.has_key('sub'):
+ querystring = """SELECT DISTINCT h.hostname, h.id, h.status
+ FROM (((((dbconvert_host h
+ INNER JOIN dbconvert_interface i ON h.id = i.host_id)
+ INNER JOIN dbconvert_ip p ON i.id = p.interface_id)
+ INNER JOIN dbconvert_name n ON p.id = n.ip_id)
+ INNER JOIN dbconvert_name_mxs x ON n.id = x.name_id)
+ INNER JOIN dbconvert_mx m ON m.id = x.mx_id)
+ LEFT JOIN dbconvert_cname c ON n.id = c.name_id
+ WHERE """
+
+ _and = False
+ for field in request.POST:
+ if request.POST[field] and field in dispatch:
+ if _and:
+ querystring += ' AND '
+ querystring += dispatch[field] % request.POST[field]
+ _and = True
+ elif request.POST[field]:
+ if _and:
+ querystring += ' AND '
+ querystring += "h.%s LIKE \'%%%%%s%%%%\'" % (field, request.POST[field])
+ _and = True
+
+
+ if not _and:
+ cursor = connection.cursor()
+ cursor.execute("""SELECT hostname, id, status
+ FROM dbconvert_host ORDER BY hostname""")
+ results = cursor.fetchall()
+ else:
+ querystring += " ORDER BY h.hostname"
+ cursor = connection.cursor()
+ cursor.execute(querystring)
+ results = cursor.fetchall()
+
+ temp = Template(open('./dbconvert/templates/results.html').read())
+ temp.hosts = results
+ return HttpResponse(str(temp))
+ else:
+ temp = Template(open('./dbconvert/templates/search.html').read())
+ temp.TYPE_CHOICES = Interface.TYPE_CHOICES
+ temp.DNS_CHOICES = Name.DNS_CHOICES
+ temp.yesno = [(1, 'yes'), (0, 'no')]
+ return HttpResponse(str(temp))
+
+def look(request, host_id):
+ """Displays general host information"""
+ temp = Template(open('./dbconvert/templates/host.html').read())
+ hostdata = gethostdata(host_id)
+ temp = fill(temp, hostdata)
+ return HttpResponse(str(temp))
+
+def dns(request, host_id):
+ temp = Template(open('./dbconvert/templates/dns.html').read())
+ hostdata = gethostdata(host_id, True)
+ temp = fill(temp, hostdata, True)
+ return HttpResponse(str(temp))
+
+def edit(request, host_id):
+ """Edit general host information
+ Data is validated before being committed to the database"""
+ # fix bug when ip address changes, update the dns info appropriately
+
+ if request.GET.has_key('sub'):
+ host = Host.objects.get(id=host_id)
+ interfaces = host.interface_set.all()
+ if not validate(request, False, host_id):
+ if (request.POST.has_key('outbound_smtp')
+ and not host.outbound_smtp or
+ not request.POST.has_key('outbound_smtp')
+ and host.outbound_smtp):
+ host.outbound_smtp = not host.outbound_smtp
+ if (request.POST.has_key('dhcp') and not host.dhcp or
+ not request.POST.has_key('dhcp') and host.dhcp):
+ host.dhcp = not host.dhcp
+ # add validation for attribs here
+ # likely use a helper fucntion
+ for attrib in attribs:
+ if request.POST.has_key(attrib):
+ host.__dict__[attrib] = request.POST[attrib]
+ if len(request.POST['expiration_date'].split("-")) == 3:
+ (year, month, day) = request.POST['expiration_date'].split("-")
+ host.expiration_date = date(int(year), int(month), int(day))
+ for inter in interfaces:
+ ips = IP.objects.filter(interface=inter.id)
+ inter.mac_addr = request.POST['mac_addr%d' % inter.id]
+ oldtype = inter.hdwr_type
+ inter.hdwr_type = request.POST['hdwr_type%d' % inter.id]
+ oldname = "-".join([host.hostname.split(".", 1)[0], oldtype])
+ oldname += "." + host.hostname.split(".", 1)[1]
+ newname = "-".join([host.hostname.split(".", 1)[0],
+ inter.hdwr_type])
+ newname += "." + host.hostname.split(".", 1)[1]
+ for name in Name.objects.filter(name=oldname):
+ name.name = newname
+ name.save()
+ for ip in ips:
+ oldip = ip.ip_addr
+ ip.ip_addr = request.POST['ip_addr%d' % ip.id]
+ ip.save()
+ oldname = "-".join([host.hostname.split(".", 1)[0],
+ oldip.split(".")[2]])
+ oldname += "." + host.hostname.split(".", 1)[1]
+ newname = "-".join([host.hostname.split(".", 1)[0],
+ ip.ip_addr.split(".")[2]])
+ newname += "." + host.hostname.split(".", 1)[1]
+ if Name.objects.filter(name=oldname):
+ name = Name.objects.get(name=oldname, ip=ip.id)
+ name.name = newname
+ name.save()
+ if request.POST['%dip_addr' % inter.id]:
+ mx, created = MX.objects.get_or_create(priority=30, mx='mailgw.mcs.anl.gov')
+ if created:
+ mx.save()
+ new_ip = IP(interface=inter, num=len(ips),
+ ip_addr=request.POST['%dip_addr' % inter.id])
+ new_ip.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_ip.ip_addr.split(".")[2]])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ name.mxs.add(mx)
+ new_name = "-".join([host.hostname.split(".")[0],
+ inter.hdwr_type])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ name.mxs.add(mx)
+ name = Name(ip=new_ip, name=host.hostname,
+ dns_view='global', only=False)
+ name.save()
+ name.mxs.add(mx)
+ inter.save()
+ if request.POST['mac_addr_new']:
+ new_inter = Interface(host=host,
+ mac_addr=request.POST['mac_addr_new'],
+ hdwr_type=request.POST['hdwr_type_new'])
+ new_inter.save()
+ if request.POST['mac_addr_new'] and request.POST['ip_addr_new']:
+ mx, created = MX.objects.get_or_create(priority=30, mx='mailgw.mcs.anl.gov')
+ if created:
+ mx.save()
+ new_ip = IP(interface=new_inter, num=0,
+ ip_addr=request.POST['ip_addr_new'])
+ new_ip.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_ip.ip_addr.split(".")[2]])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ name.mxs.add(mx)
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_inter.hdwr_type])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ name.mxs.add(mx)
+ name = Name(ip=new_ip, name=host.hostname,
+ dns_view='global', only=False)
+ name.save()
+ name.mxs.add(mx)
+ if request.POST['ip_addr_new'] and not request.POST['mac_addr_new']:
+ mx, created = MX.objects.get_or_create(priority=30, mx='mailgw.mcs.anl.gov')
+ if created:
+ mx.save()
+ new_inter = Interface(host=host, mac_addr="",
+ hdwr_type=request.POST['hdwr_type_new'])
+ new_inter.save()
+ new_ip = IP(interface=new_inter, num=0,
+ ip_addr=request.POST['ip_addr_new'])
+ new_ip.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_ip.ip_addr.split(".")[2]])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_inter.hdwr_type])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ name = Name(ip=new_ip, name=host.hostname,
+ dns_view='global', only=False)
+ name.save()
+ host.save()
+ return HttpResponseRedirect('/dbconvert/%s/' % host.id)
+ else:
+ t = Template(open('./dbconvert/templates/errors.html').read())
+ t.failures = validate(request, False, host_id)
+ return HttpResponse(str(t))
+ # examine the check boxes for any changes
+ else:
+ t = Template(open('./dbconvert/templates/edit.html').read())
+ hostdata = gethostdata(host_id)
+ t = fill(t, hostdata)
+ t.type_choices = Interface.TYPE_CHOICES
+ t.request = request
+ return HttpResponse(str(t))
+
+def confirm(request, item, item_id, host_id, name_id=None):
+ """Asks if the user is sure he/she wants to remove an item"""
+ if request.GET.has_key('sub'):
+ if item == 'interface':
+ for ip in Interface.objects.get(id=item_id).ip_set.all():
+ for name in ip.name_set.all():
+ name.cname_set.all().delete()
+ ip.name_set.all().delete()
+ Interface.objects.get(id=item_id).ip_set.all().delete()
+ Interface.objects.get(id=item_id).delete()
+ elif item=='ip':
+ for name in IP.objects.get(id=item_id).name_set.all():
+ name.cname_set.all().delete()
+ IP.objects.get(id=item_id).name_set.all().delete()
+ IP.objects.get(id=item_id).delete()
+ elif item=='cname':
+ CName.objects.get(id=item_id).delete()
+ elif item=='mx':
+ mx = MX.objects.get(id=item_id)
+ Name.objects.get(id=name_id).mxs.remove(mx)
+ elif item=='name':
+ Name.objects.get(id=item_id).cname_set.all().delete()
+ Name.objects.get(id=item_id).delete()
+ if item == 'cname' or item == 'mx' or item == 'name':
+ return HttpResponseRedirect('/dbconvert/%s/dns' % host_id)
+ else:
+ return HttpResponseRedirect('/dbconvert/%s/edit' % host_id)
+ else:
+ temp = Template(open('./dbconvert/templates/confirm.html').read())
+ interface = None
+ ips = []
+ names = {}
+ cnames = {}
+ mxs = {}
+ if item == 'interface':
+ interface = Interface.objects.get(id=item_id)
+ ips = interface.ip_set.all()
+ for ip in ips:
+ names[ip.id] = ip.name_set.all()
+ for name in names[ip.id]:
+ cnames[name.id] = name.cname_set.all()
+ mxs[name.id] = name.mx_set.all()
+ elif item=='ip':
+ ips = [IP.objects.get(id=item_id)]
+ names[ips[0].id] = ips[0].name_set.all()
+ for name in names[ips[0].id]:
+ cnames[name.id] = name.cname_set.all()
+ mxs[name.id] = name.mx_set.all()
+ elif item=='name':
+ names = [Name.objects.get(id=item_id)]
+ for name in names:
+ cnames[name.id] = name.cname_set.all()
+ mxs[name.id] = name.mxs.all()
+ elif item=='cname':
+ cnames = [CName.objects.get(id=item_id)]
+ elif item=='mx':
+ mxs = [MX.objects.get(id=item_id)]
+ temp.interface = interface
+ temp.ips = ips
+ temp.names = names
+ temp.cnames = cnames
+ temp.mxs = mxs
+ temp.id = item_id
+ temp.type = item
+ temp.host_id = host_id
+ return HttpResponse(str(temp))
+
+def dnsedit(request, host_id):
+ """Edits specific DNS information
+ Data is validated before committed to the database"""
+ if request.GET.has_key('sub'):
+ hostdata = gethostdata(host_id, True)
+ for ip in hostdata['names']:
+ ipaddr = IP.objects.get(id=ip)
+ ipaddrstr = ipaddr.__str__()
+ for name in hostdata['cnames']:
+ for cname in hostdata['cnames'][name]:
+ cname.cname = request.POST['cname%d' % cname.id]
+ cname.save()
+ for name in hostdata['mxs']:
+ for mx in hostdata['mxs'][name]:
+ mx.priority = request.POST['priority%d' % mx.id]
+ mx.mx = request.POST['mx%d' % mx.id]
+ mx.save()
+ for name in hostdata['names'][ip]:
+ name.name = request.POST['name%d' % name.id]
+ if request.POST['%dcname' % name.id]:
+ cname = CName(name=name,
+ cname=request.POST['%dcname' % name.id])
+ cname.save()
+ if (request.POST['%dpriority' % name.id] and
+ request.POST['%dmx' % name.id]):
+ mx, created = MX.objects.get_or_create(priority=request.POST['%dpriority' % name.id],
+ mx=request.POST['%dmx' % name.id])
+ if created:
+ mx.save()
+ name.mxs.add(mx)
+ name.save()
+ if request.POST['%sname' % ipaddrstr]:
+ name = Name(ip=ipaddr,
+ dns_view=request.POST['%sdns_view' % ipaddrstr],
+ name=request.POST['%sname' % ipaddrstr], only=False)
+ name.save()
+ if request.POST['%scname' % ipaddrstr]:
+ cname = CName(name=name,
+ cname=request.POST['%scname' % ipaddrstr])
+ cname.save()
+ if (request.POST['%smx' % ipaddrstr] and
+ request.POST['%spriority' % ipaddrstr]):
+ mx, created = MX.objects.get_or_create(priority=request.POST['%spriority' % ipaddrstr],
+ mx=request.POST['%smx' % ipaddrstr])
+ if created:
+ mx.save()
+ name.mxs.add(mx)
+ return HttpResponseRedirect('/dbconvert/%s/dns' % host_id)
+ else:
+ temp = Template(open('./dbconvert/templates/dnsedit.html').read())
+ hostdata = gethostdata(host_id, True)
+ temp = fill(temp, hostdata, True)
+ temp.request = request
+ return HttpResponse(str(temp))
+
+def gethostdata(host_id, dnsdata=False):
+ """Grabs the necessary data about a host
+ Replaces a lot of repeated code"""
+ hostdata = {}
+ hostdata['ips'] = {}
+ hostdata['names'] = {}
+ hostdata['cnames'] = {}
+ hostdata['mxs'] = {}
+ hostdata['host'] = Host.objects.get(id=host_id)
+ hostdata['interfaces'] = hostdata['host'].interface_set.all()
+ for interface in hostdata['interfaces']:
+ hostdata['ips'][interface.id] = interface.ip_set.all()
+ if dnsdata:
+ for ip in hostdata['ips'][interface.id]:
+ hostdata['names'][ip.id] = ip.name_set.all()
+ for name in hostdata['names'][ip.id]:
+ hostdata['cnames'][name.id] = name.cname_set.all()
+ hostdata['mxs'][name.id] = name.mxs.all()
+ return hostdata
+
+def fill(template, hostdata, dnsdata=False):
+ """Fills a generic template
+ Replaces a lot of repeated code"""
+ if dnsdata:
+ template.names = hostdata['names']
+ template.cnames = hostdata['cnames']
+ template.mxs = hostdata['mxs']
+ template.host = hostdata['host']
+ template.interfaces = hostdata['interfaces']
+ template.ips = hostdata['ips']
+ return template
+
+
+def new(request):
+ """Function for creating a new host in hostbase
+ Data is validated before committed to the database"""
+ if request.GET.has_key('sub'):
+ if not validate(request, True):
+ host = Host()
+ # this is the stuff that validate() should take care of
+ # examine the check boxes for any changes
+ host.outbound_smtp = request.POST.has_key('outbound_smtp')
+ host.dhcp = request.POST.has_key('dhcp')
+ for attrib in attribs:
+ if request.POST.has_key(attrib):
+ host.__dict__[attrib] = request.POST[attrib]
+ host.status = 'active'
+ host.save()
+ else:
+ temp = Template(open('./dbconvert/templates/errors.html').read())
+ temp.failures = validate(request, True)
+ return HttpResponse(str(temp))
+ if request.POST['mac_addr_new']:
+ new_inter = Interface(host=host,
+ mac_addr=request.POST['mac_addr_new'],
+ hdwr_type=request.POST['hdwr_type_new'])
+ new_inter.save()
+ if request.POST['mac_addr_new'] and request.POST['ip_addr_new']:
+ new_ip = IP(interface=new_inter,
+ num=0, ip_addr=request.POST['ip_addr_new'])
+ new_ip.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_ip.ip_addr.split(".")[2]])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name, dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_inter.hdwr_type])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ name = Name(ip=new_ip, name=host.hostname,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ if request.POST['ip_addr_new1'] and not request.POST['mac_addr_new1']:
+ new_inter = Interface(host=host,
+ mac_addr="",
+ hdwr_type=request.POST['hdwr_type_new1'])
+ new_inter.save()
+ new_ip = IP(interface=new_inter, num=0,
+ ip_addr=request.POST['ip_addr_new1'])
+ new_ip.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_ip.ip_addr.split(".")[2]])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_inter.hdwr_type])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ name = Name(ip=new_ip, name=host.hostname,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ if request.POST['mac_addr_new2']:
+ new_inter = Interface(host=host,
+ mac_addr=request.POST['mac_addr_new2'],
+ hdwr_type=request.POST['hdwr_addr_new2'])
+ new_inter.save()
+ if request.POST['mac_addr_new2'] and request.POST['ip_addr_new2']:
+ new_ip = IP(interface=new_inter, num=0,
+ ip_addr=request.POST['ip_addr_new2'])
+ new_ip.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_ip.ip_addr.split(".")[2]])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_inter.hdwr_type])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ name = Name(ip=new_ip, name=host.hostname,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ if request.POST['ip_addr_new2'] and not request.POST['mac_addr_new2']:
+ new_inter = Interface(host=host,
+ mac_addr="",
+ hdwr_type=request.POST['hdwr_type_new2'])
+ new_inter.save()
+ new_ip = IP(interface=new_inter, num=0,
+ ip_addr=request.POST['ip_addr_new2'])
+ new_ip.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_ip.ip_addr.split(".")[2]])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ new_name = "-".join([host.hostname.split(".")[0],
+ new_inter.hdwr_type])
+ new_name += "." + host.hostname.split(".", 1)[1]
+ name = Name(ip=new_ip, name=new_name,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ name = Name(ip=new_ip, name=host.hostname,
+ dns_view='global', only=False)
+ name.save()
+ mx = MX(name=name, priority=30, mx='mailgw.mcs.anl.gov')
+ mx.save()
+ host.save()
+ return HttpResponseRedirect('/dbconvert/%s/' % host.id)
+ else:
+ temp = Template(open('./dbconvert/templates/new.html').read())
+ temp.TYPE_CHOICES = Interface.TYPE_CHOICES
+ temp.NETGROUP_CHOICES = Host.NETGROUP_CHOICES
+ temp.CLASS_CHOICES = Host.CLASS_CHOICES
+ temp.SUPPORT_CHOICES = Host.SUPPORT_CHOICES
+ temp.failures = False
+ return HttpResponse(str(temp))
+
+def validate(request, new=False, host_id=None):
+ """Function for checking form data"""
+ failures = []
+ dateregex = re.compile('^[0-9]{4}-[0-9]{2}-[0-9]{2}$')
+ if (request.POST['expiration_date']
+ and dateregex.match(request.POST['expiration_date'])):
+ try:
+ (year, month, day) = request.POST['expiration_date'].split("-")
+ date(int(year), int(month), int(day))
+ except (ValueError):
+ failures.append('expiration_date')
+ elif request.POST['expiration_date']:
+ failures.append('expiration_date')
+
+ hostregex = re.compile('^[a-z0-9-_]+(\.[a-z0-9-_]+)+$')
+ if not (request.POST['hostname']
+ and hostregex.match(request.POST['hostname'])):
+ failures.append('hostname')
+
+ printregex = re.compile('^[a-z0-9-]+$')
+ if not printregex.match(request.POST['printq']) and request.POST['printq']:
+ failures.append('printq')
+
+ userregex = re.compile('^[a-z0-9-_\.@]+$')
+ if not userregex.match(request.POST['primary_user']):
+ failures.append('primary_user')
+
+ if (not userregex.match(request.POST['administrator'])
+ and request.POST['administrator']):
+ failures.append('administrator')
+
+ locationregex = re.compile('^[0-9]{3}-[a-z][0-9]{3}$|none|bmr|cave|dsl|evl|mobile|offsite|mural|activespaces')
+ if not (request.POST['location']
+ and locationregex.match(request.POST['location'])):
+ failures.append('location')
+
+ if new:
+ macaddr_regex = re.compile('^[0-9abcdef]{2}(:[0-9abcdef]{2}){5}$')
+ if (not macaddr_regex.match(request.POST['mac_addr_new'])
+ and request.POST['mac_addr_new']):
+ failures.append('mac_addr (#1)')
+ if ((request.POST['mac_addr_new'] or request.POST['ip_addr_new']) and
+ not request.has_key('hdwr_type_new')):
+ failures.append('hdwr_type (#1)')
+ if ((request.POST['mac_addr_new2'] or request.POST['ip_addr_new']) and
+ not request.has_key('hdwr_type_new2')):
+ failures.append('hdwr_type (#2)')
+
+ if (not macaddr_regex.match(request.POST['mac_addr_new2'])
+ and request.POST['mac_addr_new2']):
+ failures.append('mac_addr (#2)')
+
+ ipaddr_regex = re.compile('^[0-9]{1,3}(\.[0-9]{1,3}){3}$')
+ if (not ipaddr_regex.match(request.POST['ip_addr_new'])
+ and request.POST['ip_addr_new']):
+ failures.append('ip_addr (#1)')
+ if (not ipaddr_regex.match(request.POST['ip_addr_new2'])
+ and request.POST['ip_addr_new2']):
+ failures.append('ip_addr (#2)')
+
+ [failures.append('ip_addr (#1)') for number in
+ request.POST['ip_addr_new'].split(".")
+ if number.isdigit() and int(number) > 255
+ and 'ip_addr (#1)' not in failures]
+ [failures.append('ip_addr (#2)') for number in
+ request.POST['ip_addr_new2'].split(".")
+ if number.isdigit() and int(number) > 255
+ and 'ip_addr (#2)' not in failures]
+
+ elif host_id:
+ macaddr_regex = re.compile('^[0-9abcdef]{2}(:[0-9abcdef]{2}){5}$')
+ ipaddr_regex = re.compile('^[0-9]{1,3}(\.[0-9]{1,3}){3}$')
+ interfaces = Interface.objects.filter(host=host_id)
+ for interface in interfaces:
+ if (not macaddr_regex.match(request.POST['mac_addr%d' % interface.id])
+ and request.POST['mac_addr%d' % interface.id]):
+ failures.append('mac_addr (%s)' % request.POST['mac_addr%d' % interface.id])
+ for ip in interface.ip_set.all():
+ if not ipaddr_regex.match(request.POST['ip_addr%d' % ip.id]):
+ failures.append('ip_addr (%s)' % request.POST['ip_addr%d' % ip.id])
+ [failures.append('ip_addr (%s)' % request.POST['ip_addr%d' % ip.id])
+ for number in request.POST['ip_addr%d' % ip.id].split(".")
+ if (number.isdigit() and int(number) > 255 and
+ 'ip_addr (%s)' % request.POST['ip_addr%d' % ip.id] not in failures)]
+
+
+
+
+ if not failures:
+ return 0
+ return failures
diff --git a/src/lib/Server/Plugins/Hostbase.py b/src/lib/Server/Plugins/Hostbase.py
index 96f215451..3711ec5d3 100644
--- a/src/lib/Server/Plugins/Hostbase.py
+++ b/src/lib/Server/Plugins/Hostbase.py
@@ -1,42 +1,41 @@
'''This file provides the Hostbase plugin. It manages dns/dhcp/nis host information'''
__revision__ = '$Revision$'
-from lxml.etree import XML, SubElement
+from lxml.etree import Element, SubElement
+from django.db import connection
+from syslog import syslog, LOG_INFO
from Cheetah.Template import Template
from Bcfg2.Server.Plugin import Plugin, PluginExecutionError, PluginInitError, DirectoryBacked
from time import strftime
from sets import Set
import re
-import logging
-logger = logging.getLogger('Bcfg2.Plugins.Hostbase')
+## class DataNexus(DirectoryBacked):
+## '''DataNexus is an object that watches multiple files and
+## handles changes in an intelligent fashion.'''
+## __name__ = 'DataNexus'
-class DataNexus(DirectoryBacked):
- '''DataNexus is an object that watches multiple files and
- handles changes in an intelligent fashion.'''
- __name__ = 'DataNexus'
-
- def __init__(self, path, filelist, fam):
- self.files = filelist
- DirectoryBacked.__init__(self, path, fam)
+## def __init__(self, path, filelist, fam):
+## self.files = filelist
+## DirectoryBacked.__init__(self, path, fam)
- def HandleEvent(self, event):
- '''Trap adds and updates, else call baseclass HandleEvent'''
- action = event.code2str()
- if action in ['exists', 'created']:
- if (event.filename != self.name) and (event.filename not in self.files):
- logger.info("%s:Got event for unexpected file %s" % (self.__name__, event.filename))
- return
- DirectoryBacked.HandleEvent(self, event)
- if action != 'endExist' and event.filename != self.name:
- self.rebuildState(event)
-
- def rebuildState(self, event):
- '''This function is called when underlying data has changed'''
- pass
-
-class Hostbase(Plugin, DataNexus):
+## def HandleEvent(self, event):
+## '''Trap adds and updates, else call baseclass HandleEvent'''
+## action = event.code2str()
+## if action in ['exists', 'created']:
+## if (event.filename != self.name) and (event.filename not in self.files):
+## syslog(LOG_INFO, "%s:Got event for unexpected file %s" % (self.__name__, event.filename))
+## return
+## DirectoryBacked.HandleEvent(self, event)
+## if action != 'endExist' and event.filename != self.name:
+## self.rebuildState(event)
+
+## def rebuildState(self, event):
+## '''This function is called when underlying data has changed'''
+## pass
+
+class Hostbase(Plugin):
'''The Hostbase plugin handles host/network info'''
__name__ = 'Hostbase'
__version__ = '$Id$'
@@ -44,28 +43,41 @@ class Hostbase(Plugin, DataNexus):
filepath = '/etc/bind'
def __init__(self, core, datastore):
+
self.ready = False
- files = ['zones.xml', 'hostbase.xml', 'hostbase-dns.xml', 'hostbase-dhcp.xml']
Plugin.__init__(self, core, datastore)
- try:
- DataNexus.__init__(self, datastore + '/Hostbase/data',
- files, self.core.fam)
- except:
- logger.error("Failed to load data directory")
- raise PluginInitError
- self.xdata = {}
+## try:
+## DataNexus.__init__(self, datastore + '/Hostbase/data',
+## files, self.core.fam)
+## except:
+## self.LogError("Failed to load data directory")
+## raise PluginInitError
self.filedata = {}
- self.dnsservers = ['scotty.mcs.anl.gov']
- self.dhcpservers = ['thwap.mcs.anl.gov', 'squeak.mcs.anl.gov']
+ self.dnsservers = []
+ self.dhcpservers = []
self.templates = {'zone':Template(open(self.data + '/templates/' + 'zonetemplate.tmpl').read()),
'reversesoa':Template(open(self.data + '/templates/' + 'reversesoa.tmpl').read()),
'named':Template(open(self.data + '/templates/' + 'namedtemplate.tmpl').read()),
'reverseapp':Template(open(self.data + '/templates/' + 'reverseappend.tmpl').read()),
'dhcp':Template(open(self.data + '/templates/' + 'dhcpd_template.tmpl').read()),
'hosts':Template(open(self.data + '/templates/' + 'hosts.tmpl').read()),
- 'hostsapp':Template(open(self.data + '/templates/' + 'hostsappend.tmpl').read())}
+ 'hostsapp':Template(open(self.data + '/templates/' + 'hostsappend.tmpl').read()),
+ }
self.Entries['ConfigFile'] = {}
+ def get_serial(self, zonefile):
+ """Updates the serial number for a particular zone file"""
+ todaydate = (strftime('%Y%m%d'))
+ try:
+ if todaydate == str(zonefile[2])[:8]:
+ serial = zonefile[2] + 1
+ else:
+ serial = int(todaydate) * 100
+ return str(serial)
+ except (KeyError):
+ serial = int(todaydate) * 100
+ return str(serial)
+
def FetchFile(self, entry, metadata):
'''Return prebuilt file data'''
fname = entry.get('name').split('/')[-1]
@@ -77,144 +89,175 @@ class Hostbase(Plugin, DataNexus):
def BuildStructures(self, metadata):
'''Build hostbase bundle'''
- if metadata.hostname in self.dnsservers or metadata.hostname in self.dhcpservers:
- output = []
- if metadata.hostname in self.dnsservers:
- dnsbundle = XML(self.entries['hostbase-dns.xml'].data)
- for configfile in self.Entries['ConfigFile']:
- if re.search('/etc/bind/', configfile):
- SubElement(dnsbundle, "ConfigFile", name=configfile)
- output.append(dnsbundle)
- if metadata.hostname in self.dhcpservers:
- dhcpbundle = XML(self.entries['hostbase-dhcp.xml'].data)
- output.append(dhcpbundle)
- return output
- else:
+ if metadata.hostname not in self.dnsservers or metadata.hostname not in self.dhcpservers:
return []
+ output = Element("Bundle", name='hostbase')
+ if metadata.hostname in self.dnsservers:
+ for configfile in self.Entries['ConfigFile']:
+ if re.search('/etc/bind/', configfile):
+ SubElement(output, "ConfigFile", name=configfile)
+ if metadata.hostname in self.dhcpservers:
+ SubElement(output, "ConfigFile", name="/etc/dhcpd.conf")
+ return [output]
def rebuildState(self, event):
'''Pre-cache all state information for hostbase config files'''
- def get_serial(zone):
- '''I think this does the zone file serial number hack but whatever'''
+
+ cursor = connection.cursor()
+
+ cursor.execute("SELECT id, serial FROM dbconvert_zone")
+ zones = cursor.fetchall()
+
+ for zone in zones:
+ # update the serial number for all zone files
todaydate = (strftime('%Y%m%d'))
try:
- if todaydate == zone.get('serial')[:8]:
- serial = int(zone.get('serial')) + 1
+ if todaydate == str(zone[1])[:8]:
+ serial = zone[1] + 1
else:
serial = int(todaydate) * 100
return str(serial)
except (KeyError):
serial = int(todaydate) * 100
- return str(serial)
+ cursor.execute("""UPDATE dbconvert_zone SET serial = \'%s\' WHERE id = \'%s\'""" % (str(serial), zone[0]))
- if self.entries.has_key(event.filename) and not self.xdata.has_key(event.filename):
- self.xdata[event.filename] = XML(self.entries[event.filename].data)
- if [item for item in self.files if not self.entries.has_key(item)]:
- return
- # we might be able to rebuild data more sparsely,
- # but hostbase.xml is the only one that will really change often
- # rebuild zoneinfo
+ cursor.execute("SELECT * FROM dbconvert_zone")
+ zones = cursor.fetchall()
+
+ iplist = []
hosts = {}
- zones = self.xdata['zones.xml']
- hostbase = self.xdata['hostbase.xml']
- ## this now gets all hosts associated with the zone file being initialized
- ## all ip addresses and cnames are grabbed from each host and passed to the appropriate template
+
for zone in zones:
- hosts[zone.get('domain')] = []
- for host in hostbase:
- if host.get('domain') in hosts:
- hosts[host.get('domain')].append(host)
+ if zone[1] == 'mcs.anl.gov':
+ reversezone = zone
+ cursor.execute("""SELECT n.name FROM dbconvert_zone_nameservers z
+ INNER JOIN dbconvert_nameserver n ON z.nameserver_id = n.id
+ WHERE z.zone_id = \'%s\'""" % zone[0])
+ mcs_nameservers = cursor.fetchall()
+
+
for zone in zones:
- zonehosts = []
- for host in hosts[zone.get('domain')]:
- hostname = host.attrib['hostname']
- ipnodes = host.findall("interface/ip")
- #gets all the forward look up stuff
- [zonehosts.append((namenode.get('name').split(".")[0], ipnode.get('ip'),
- namenode.findall('mx')))
- for ipnode in ipnodes
- for namenode in ipnode]
- #gets cname stuff
- [zonehosts.append((cnamenode.get('cname') + '.', namenode.get('name').split('.')[0], None))
- for namenode in host.findall("interface/ip/name")
- for cnamenode in namenode.findall("cname")
- if (cnamenode.get('cname').split(".")[0], namenode.get('name').split('.')[0], None) not in zonehosts
- and cnamenode.get('cname') is not None]
-
- zonehosts.sort()
self.templates['zone'].zone = zone
- self.templates['zone'].root = zones
- self.templates['zone'].hosts = zonehosts
- self.filedata[zone.get('domain')] = str(self.templates['zone'])
- self.Entries['ConfigFile']["%s/%s" % (self.filepath, zone.get('domain'))] = self.FetchFile
- # now all zone forward files are built
+ cursor.execute("""SELECT n.name FROM dbconvert_zone_nameservers z
+ INNER JOIN dbconvert_nameserver n ON z.nameserver_id = n.id
+ WHERE z.zone_id = \'%s\'""" % zone[0])
+ self.templates['zone'].nameservers = cursor.fetchall()
+ cursor.execute("""SELECT i.ip_addr FROM dbconvert_zone_addresses z
+ INNER JOIN dbconvert_ip i ON z.ip_id = i.id
+ WHERE z.zone_id = \'%s\'""" % zone[0])
+ self.templates['zone'].addresses = cursor.fetchall()
+ cursor.execute("""SELECT m.priority, m.mx FROM dbconvert_zone_mxs z
+ INNER JOIN dbconvert_mx m ON z.mx_id = m.id
+ WHERE z.zone_id = \'%s\'""" % zone[0])
+ self.templates['zone'].mxs = cursor.fetchall()
+ self.filedata[zone[1]] = str(self.templates['zone'])
+
+ querystring = """SELECT h.hostname, p.ip_addr,
+ n.name, c.cname, m.priority, m.mx
+ FROM (((((dbconvert_host h INNER JOIN dbconvert_interface i ON h.id = i.host_id)
+ INNER JOIN dbconvert_ip p ON i.id = p.interface_id)
+ INNER JOIN dbconvert_name n ON p.id = n.ip_id)
+ INNER JOIN dbconvert_name_mxs x ON n.id = x.name_id)
+ INNER JOIN dbconvert_mx m ON m.id = x.mx_id)
+ LEFT JOIN dbconvert_cname c ON n.id = c.name_id
+ WHERE h.hostname LIKE '%%%%%s' AND h.status = 'active'
+ ORDER BY h.hostname, n.name, p.ip_addr
+ """ % zone[1]
+ cursor.execute(querystring)
+ zonehosts = cursor.fetchall()
+## hosts[zone[1]] = zonehosts
+ prevhost = (None, None, None, None)
+ for host in zonehosts:
+ if not host[0].split(".", 1)[1] == zone[1]:
+ continue
+ if not prevhost[1] == host[1] or not prevhost[2] == host[2]:
+ self.filedata[zone[1]] += ("%-32s%-10s%-32s\n" %
+ (host[2].split(".", 1)[0], 'A', host[1]))
+ self.filedata[zone[1]] += ("%-32s%-10s%-3s%-29s\n" %
+ ('', 'MX', host[4], host[5].split(".", 1)[0]))
+ if host[3]:
+ if host[3].split(".", 1)[1] == zone[1]:
+ self.filedata[zone[1]] += ("%-32s%-10s%-32s\n" %
+ (host[3].split(".", 1)[0],
+ 'CNAME',host[2].split(".", 1)[0]))
+ else:
+ self.filedata[zone[1]] += ("%-32s%-10s%-32s\n" %
+ (host[3]+".",
+ 'CNAME',
+ host[2].split(".", 1)[0]))
+ prevhost = host
+ self.filedata[zone[1]] += ("\n\n%s" % zone[9])
+
+ self.Entries['ConfigFile']["%s/%s" % (self.filepath, zone[1])] = self.FetchFile
+
+
filelist = []
- three_subnet = [ip.get('ip').rstrip('0123456789').rstrip('.')
- for ip in hostbase.findall('host/interface/ip')]
+ cursor.execute("""
+ SELECT ip_addr FROM dbconvert_ip ORDER BY ip_addr
+ """)
+ three_subnet = [ip[0].rstrip('0123456789').rstrip('.') \
+ for ip in cursor.fetchall()]
three_subnet_set = Set(three_subnet)
- two_subnet = [subnet.rstrip('0123456789').rstrip('.')
+ two_subnet = [subnet.rstrip('0123456789').rstrip('.') \
for subnet in three_subnet_set]
two_subnet_set = Set(two_subnet)
- filelist = [each for each in two_subnet_set
+ filelist = [each for each in two_subnet_set \
if two_subnet.count(each) > 1]
- [filelist.append(each) for each in three_subnet_set
- if each.rstrip('0123456789').rstrip('.') not in filelist]
-
+ for each in three_subnet_set:
+ if each.rstrip('0123456789').rstrip('.') not in filelist:
+ filelist.append(each)
+
reversenames = []
for filename in filelist:
towrite = filename.split('.')
towrite.reverse()
reversename = '.'.join(towrite)
self.templates['reversesoa'].inaddr = reversename
- self.templates['reversesoa'].zone = zone
- self.templates['reversesoa'].root = self.xdata['zones.xml']
+ self.templates['reversesoa'].zone = reversezone
+ self.templates['reversesoa'].nameservers = mcs_nameservers
self.filedata['%s.rev' % reversename] = str(self.templates['reversesoa'])
- reversenames.append(reversename)
+ reversenames.append((reversename, filename))
- self.templates['named'].zones = self.xdata['zones.xml']
+ ## here's where the named.conf file gets written
+ self.templates['named'].zones = zones
self.templates['named'].reverses = reversenames
- self.filedata["named.conf"] = str(self.templates['named'])
- self.Entries['ConfigFile']["%s/%s" % (self.filepath, 'named.conf')] = self.FetchFile
+ self.filedata['named.conf'] = str(self.templates['named'])
+ self.Entries['ConfigFile']['%s/named.conf' % self.filepath] = self.FetchFile
reversenames.sort()
for filename in reversenames:
originlist = []
- reversehosts = []
- towrite = filename.split(".")
- towrite.reverse()
- if len(towrite) > 2:
- [reversehosts.append((ipnode.attrib['ip'].split("."), host.attrib['hostname'],
- host.attrib['domain'], ipnode.get('num'), None))
- for host in self.xdata['hostbase.xml']
- for ipnode in host.findall("interface/ip")
- if ipnode.attrib['ip'].split(".")[:3] == towrite]
- self.templates['reverseapp'].hosts = reversehosts
- self.templates['reverseapp'].inaddr = filename
- self.templates['reverseapp'].fileorigin = None
- self.filedata["%s.rev" % filename] += str(self.templates['reverseapp'])
- else:
- [reversehosts.append((ipnode.attrib['ip'].split("."), host.attrib['hostname'],
- host.attrib['domain'], ipnode.get('num'), None))
- for host in self.xdata['hostbase.xml']
- for ipnode in host.findall("interface/ip")
- if ipnode.attrib['ip'].split(".")[:2] == towrite]
-
- [originlist.append(".".join([reversehost[0][2], reversehost[0][1], reversehost[0][0]]))
- for reversehost in reversehosts
- if ".".join([reversehost[0][2], reversehost[0][1], reversehost[0][0]]) not in originlist]
-
- reversehosts.sort()
- originlist.sort()
+ cursor.execute("""
+ SELECT h.hostname, p.ip_addr, p.num FROM ((dbconvert_host h
+ INNER JOIN dbconvert_interface i ON h.id = i.host_id)
+ INNER JOIN dbconvert_ip p ON i.id = p.interface_id)
+ WHERE p.ip_addr LIKE '%s%%%%' AND h.status = 'active' ORDER BY p.ip_addr
+ """ % filename[1])
+ reversehosts = cursor.fetchall()
+ if len(filename[0].split(".")) == 2:
+ [originlist.append((".".join([ip[1].split(".")[2], filename[0]]),
+ ".".join([filename[1], ip[1].split(".")[2]])))
+ for ip in reversehosts
+ if (".".join([ip[1].split(".")[2], filename[0]]),
+ ".".join([filename[1], ip[1].split(".")[2]])) not in originlist]
for origin in originlist:
- outputlist = []
- [outputlist.append(reversehost)
- for reversehost in reversehosts
- if ".".join([reversehost[0][2], reversehost[0][1], reversehost[0][0]]) == origin]
- self.templates['reverseapp'].fileorigin = filename
- self.templates['reverseapp'].hosts = outputlist
- self.templates['reverseapp'].inaddr = origin
- self.filedata["%s.rev" % filename] += str(self.templates['reverseapp'])
- self.Entries['ConfigFile']["%s/%s.rev" % (self.filepath, filename)] = self.FetchFile
+ hosts = [host.__add__((host[1].split("."), host[0].split(".", 1)))
+ for host in reversehosts
+ if host[1].rstrip('0123456789').rstrip('.') == origin[1]]
+ self.templates['reverseapp'].hosts = hosts
+ self.templates['reverseapp'].inaddr = origin[0]
+ self.templates['reverseapp'].fileorigin = filename[0]
+ self.filedata['%s.rev' % filename[0]] += str(self.templates['reverseapp'])
+ else:
+ originlist = [filename[0]]
+ hosts = [host.__add__((host[1].split("."), host[0].split(".", 1)))
+ for host in reversehosts]
+ self.templates['reverseapp'].hosts = hosts
+ self.templates['reverseapp'].inaddr = filename[0]
+ self.templates['reverseapp'].fileorigin = None
+ self.filedata['%s.rev' % filename[0]] += str(self.templates['reverseapp'])
+ self.Entries['ConfigFile']['%s/%s.rev' % (self.filepath, filename[0])] = self.FetchFile
+
self.buildDHCP()
self.buildHosts()
self.buildHostsLPD()
@@ -223,184 +266,259 @@ class Hostbase(Plugin, DataNexus):
def buildDHCP(self):
'''Pre-build dhcpd.conf and stash in the filedata table'''
- if 'hostbase.xml' not in self.xdata.keys():
- print "not running before hostbase is cached"
- return
- hostbase = self.xdata['hostbase.xml']
- dhcphosts = [host for host in hostbase if host.find('dhcp').get('dhcp') == 'y'
- and host.find("interface").attrib['mac'] != 'float'
- and host.find("interface").attrib['mac'] != ""
- and host.find("interface").attrib['mac'] != "unknown"]
-
- numips = 0
+
+ # fetches all the hosts with DHCP == True
+ cursor = connection.cursor()
+ cursor.execute("""
+ SELECT hostname, mac_addr, ip_addr
+ FROM (dbconvert_host h INNER JOIN dbconvert_interface i ON h.id = i.host_id)
+ INNER JOIN dbconvert_ip ip ON i.id = ip.interface_id
+ WHERE h.dhcp=1 AND h.status = 'active'
+ ORDER BY h.hostname, i.mac_addr
+ """)
+
+ dhcphosts = cursor.fetchall()
+ count = 0
hosts = []
- for host in dhcphosts:
- if len(host.findall("interface")) == 1 and len(host.findall("interface/ip")) == 1:
- hosts.append([host.attrib['hostname'], host.attrib['domain'], \
- host.find("interface").attrib['mac'], \
- host.find("interface/ip").attrib['ip']])
+ hostdata = [dhcphosts[0][0], dhcphosts[0][1], dhcphosts[0][2]]
+ for x in range(1, len(cursor.fetchall())-1):
+ # if an interface has 2 or more ip addresses
+ # adds the ip to the current interface
+ if hostdata[0] == dhcphosts[x][0] and hostdata[1] == dhcphosts[x][1]:
+ hostdata[2] = ", ".join([hostdata[2], dhcphosts[x][2]])
+ # if a host has 2 or more interfaces
+ # writes the current one and grabs the next
+ elif hostdata[0] == dhcphosts[x][0]:
+ hosts.append(hostdata)
+ count += 1
+ hostdata = [dhcphosts[x][0], dhcphosts[x][1], dhcphosts[x][2]]
+ # new host found, writes current data to the template
else:
+ if count:
+ hostdata[0] = "-".join([hostdata[0], str(count)])
+ hosts.append(hostdata)
count = 0
- for interface in host.findall('interface'):
- if count == 0 and interface.find("ip") is not None:
- hostdata = [host.attrib['hostname'], host.attrib['domain'],
- interface.attrib['mac'], interface.find("ip").attrib['ip']]
- elif count != 0 and interface.find("ip") is not None:
- hostdata = [host.attrib['hostname'], "-".join([host.attrib['domain'], str(count)]),
- interface.attrib['mac'], interface.find("ip").attrib['ip']]
- if len(interface.findall("ip")) > 1:
- for ip in interface.findall("ip")[1:]:
- hostdata[3] = ", ".join([hostdata[3], ip.attrib['ip']])
- count += 1
- hosts.append(hostdata)
-
- numips += len(host.findall("interface/ip"))
-
- hosts.sort(lambda x, y: cmp(x[0], y[0]))
+ hostdata = [dhcphosts[x][0], dhcphosts[x][1], dhcphosts[x][2]]
+ #makes sure the last of the data gets written out
+ if hostdata not in hosts:
+ hosts.append(hostdata)
+
self.templates['dhcp'].hosts = hosts
- self.templates['dhcp'].numips = numips
+ self.templates['dhcp'].numips = len(hosts)
self.templates['dhcp'].timecreated = strftime("%a %b %d %H:%M:%S %Z %Y")
+
self.filedata['dhcpd.conf'] = str(self.templates['dhcp'])
self.Entries['ConfigFile']['/etc/dhcpd.conf'] = self.FetchFile
+
def buildHosts(self):
- '''This will rebuild the hosts file to include all important machines'''
- hostbase = self.xdata['hostbase.xml']
- domains = [host.get('domain') for host in hostbase]
+
+ append_data = []
+
+ cursor = connection.cursor()
+ cursor.execute("""
+ SELECT hostname FROM dbconvert_host ORDER BY hostname
+ """)
+ hostbase = cursor.fetchall()
+ domains = [host[0].split(".", 1)[1] for host in hostbase]
domains_set = Set(domains)
domain_data = [(domain, domains.count(domain)) for domain in domains_set]
domain_data.sort()
- ips = [(ip, host) for host in hostbase.findall('host')
- for ip in host.findall("interface/ip")]
- three_octets = [ip[0].get('ip').rstrip('0123456789').rstrip('.')
+
+ cursor.execute("""
+ SELECT ip_addr FROM dbconvert_ip ORDER BY ip_addr
+ """)
+ ips = cursor.fetchall()
+ three_octets = [ip[0].rstrip('0123456789').rstrip('.') \
for ip in ips]
- three_octets_set = list(Set(three_octets))
- three_sort = [tuple([int(num) for num in each.split('.')]) for each in three_octets_set]
- three_sort.sort()
- three_octets_set = ['.'.join([str(num) for num in each]) for each in three_sort]
- three_octets_data = [(octet, three_octets.count(octet))
+ three_octets_set = Set(three_octets)
+ three_octets_data = [(octet, three_octets.count(octet)) \
for octet in three_octets_set]
- append_data = [(subnet, [ip for ip in ips \
- if ip[0].get('ip').rstrip("0123456789").rstrip('.')
- == subnet[0]]) for subnet in three_octets_data]
- for each in append_data:
- each[1].sort(lambda x, y: cmp(int(x[0].get('ip').split('.')[-1]), int(y[0].get('ip').split('.')[-1])))
+ three_octets_data.sort()
+
+ for three_octet in three_octets_data:
+ querystring = """SELECT h.hostname, h.primary_user,
+ p.ip_addr, n.name, c.cname
+ FROM (((dbconvert_host h INNER JOIN dbconvert_interface i ON h.id = i.host_id)
+ INNER JOIN dbconvert_ip p ON i.id = p.interface_id)
+ INNER JOIN dbconvert_name n ON p.id = n.ip_id)
+ LEFT JOIN dbconvert_cname c ON n.id = c.name_id
+ WHERE p.ip_addr LIKE \'%s%%%%\' AND h.status = 'active'
+ ORDER BY p.ip_addr""" % three_octet[0]
+ cursor.execute(querystring)
+ append_data.append((three_octet, cursor.fetchall()))
+
two_octets = [ip.rstrip('0123456789').rstrip('.') for ip in three_octets]
- two_octets_set = list(Set(two_octets))
- two_sort = [tuple([int(num) for num in each.split('.')]) for each in two_octets_set]
- two_sort.sort()
- two_octets_set = ['.'.join([str(num) for num in each]) for each in two_sort]
- two_octets_data = [(octet, two_octets.count(octet)) for octet in two_octets_set]
+ two_octets_set = Set(two_octets)
+ two_octets_data = [(octet, two_octets.count(octet))
+ for octet in two_octets_set]
+ two_octets_data.sort()
+
self.templates['hosts'].domain_data = domain_data
self.templates['hosts'].three_octets_data = three_octets_data
self.templates['hosts'].two_octets_data = two_octets_data
self.templates['hosts'].three_octets = len(three_octets)
- self.templates['hosts'].timecreated = strftime("%a %b %d %H:%M:%S %Z %Y")
self.filedata['hosts'] = str(self.templates['hosts'])
+
for subnet in append_data:
- self.templates['hostsapp'].ips = subnet[1]
+ ips = []
+ simple = True
+ namelist = [subnet[1][0][3]]
+ cnamelist = []
+ if subnet[1][0][4]:
+ cnamelist.append(subnet[1][0][4])
+ simple = False
+ appenddata = subnet[1][0]
+ for ip in subnet[1][1:]:
+ if appenddata[2] == ip[2]:
+ namelist.append(ip[3])
+ if ip[4]:
+ cnamelist.append(ip[4])
+ simple = False
+ appenddata = ip
+ else:
+ if appenddata[0] == ip[0]:
+ simple = False
+ ips.append((appenddata[2], appenddata[0], namelist,
+ cnamelist, simple, appenddata[1]))
+ appenddata = ip
+ simple = True
+ namelist = [ip[3]]
+ cnamelist = []
+ if ip[4]:
+ cnamelist.append(ip[4])
+ simple = False
+ ips.append((appenddata[2], appenddata[0], namelist,
+ cnamelist, simple, appenddata[1]))
self.templates['hostsapp'].subnet = subnet[0]
+ self.templates['hostsapp'].ips = ips
self.filedata['hosts'] += str(self.templates['hostsapp'])
self.Entries['ConfigFile']['/mcs/etc/hosts'] = self.FetchFile
-
def buildPrinters(self):
- '''this will rebuild the printers.data file used in
- our local printers script'''
+ """The /mcs/etc/printers.data file"""
header = """# This file is automatically generated. DO NOT EDIT IT!
-# This datafile is for use with /mcs/bin/printers.
-#
-Name Room User Type Notes
-============== ========== ============ ======================== ====================
-"""
-
- printers = [host for host in self.xdata['hostbase.xml']
- if host.find('whatami').get('whatami') == "printer"
- and host.get('domain') == 'mcs.anl.gov']
- self.filedata['printers.data'] = header
- output_list = []
+ # To update the contents of this file execute a 'make printers'
+ # and then an 'install printers' in /mcs/adm/hostbase as root
+ # on antares. This datafile is for use with /mcs/bin/printers.
+ #
+ Name Room User Type Notes
+ ============== ========== ============================== ======================== ====================
+ """
+
+ cursor = connection.cursor()
+ # fetches all the printers from the database
+ cursor.execute("""
+ SELECT printq, location, primary_user, comments
+ FROM dbconvert_host
+ WHERE whatami='printer' AND printq <> '' AND status = 'active'
+ ORDER BY printq
+ """)
+ printers = cursor.fetchall()
+
+ printersfile = header
for printer in printers:
- if printer.find('printq').get('printq'):
- for printq in re.split(',[ ]*', printer.find('printq').get('printq')):
- output_list.append((printq, printer.find('room').get('room'), printer.find('user').get('user'),
- printer.find('model').get('model'), printer.find('note').get('note')))
- output_list.sort()
- for printer in output_list:
- self.filedata['printers.data'] += ("%-16s%-12s%-14s%-26s%s\n" % printer)
+ # splits up the printq line and gets the
+ # correct description out of the comments section
+ temp = printer[3].split('\n')
+ for printq in re.split(',[ ]*', printer[0]):
+ if len(temp) > 1:
+ printersfile += ("%-16s%-12s%-32s%-26s%s\n" %
+ (printq, printer[1], printer[2], temp[1], temp[0]))
+ else:
+ printersfile += ("%-16s%-12s%-32s%-26s%s\n" %
+ (printq, printer[1], printer[2], '', printer[3]))
+ print 'Done!'
+ self.filedata['printers.data'] = printersfile
self.Entries['ConfigFile']['/mcs/etc/printers.data'] = self.FetchFile
def buildHostsLPD(self):
- '''this rebuilds the hosts.lpd file'''
+ """Creates the /mcs/etc/hosts.lpd file"""
+
header = """+@machines
-+@all-machines
-achilles.ctd.anl.gov
-raven.ops.anl.gov
-seagull.hr.anl.gov
-parrot.ops.anl.gov
-condor.ops.anl.gov
-delphi.esh.anl.gov
-anlcv1.ctd.anl.gov
-anlvms.ctd.anl.gov
-olivia.ctd.anl.gov\n\n"""
-
- hostbase = self.xdata['hostbase.xml']
- redmachines = [".".join([host.get('hostname'), host.get('domain')])
- for host in hostbase if host.find('netgroup').get('netgroup') == 'red']
- winmachines = [".".join([host.get('hostname'), host.get('domain')])
- for host in hostbase if host.find('netgroup').get('netgroup') == 'win']
- redmachines += [name.get('name') for host in hostbase
- for name in host.findall('interface/ip/name')
- if host.find('netgroup').get('netgroup') == 'red' and name.get('only') != 'no']
- winmachines += [name.get('name') for host in hostbase
- for name in host.findall('interface/ip/name')
- if host.find('netgroup').get('netgroup') == 'win' and name.get('only') != 'no']
- redmachines.sort()
- winmachines.sort()
- self.filedata['hosts.lpd'] = header
+ +@all-machines
+ achilles.ctd.anl.gov
+ raven.ops.anl.gov
+ seagull.hr.anl.gov
+ parrot.ops.anl.gov
+ condor.ops.anl.gov
+ delphi.esh.anl.gov
+ anlcv1.ctd.anl.gov
+ anlvms.ctd.anl.gov
+ olivia.ctd.anl.gov\n\n"""
+
+ cursor = connection.cursor()
+ cursor.execute("""
+ SELECT hostname FROM dbconvert_host WHERE netgroup=\"red\" AND status = 'active'
+ ORDER BY hostname""")
+ redmachines = list(cursor.fetchall())
+ cursor.execute("""
+ SELECT n.name FROM ((dbconvert_host h INNER JOIN dbconvert_interface i ON h.id = i.host_id)
+ INNER JOIN dbconvert_ip p ON i.id = p.interface_id) INNER JOIN dbconvert_name n ON p.id = n.ip_id
+ WHERE netgroup=\"red\" AND n.only=1 AND h.status = 'active'
+ """)
+ redmachines.extend(list(cursor.fetchall()))
+ cursor.execute("""
+ SELECT hostname FROM dbconvert_host WHERE netgroup=\"win\" AND status = 'active'
+ ORDER BY hostname""")
+ winmachines = list(cursor.fetchall())
+ cursor.execute("""
+ SELECT n.name FROM ((dbconvert_host h INNER JOIN dbconvert_interface i ON h.id = i.host_id)
+ INNER JOIN dbconvert_ip p ON i.id = p.interface_id) INNER JOIN dbconvert_name n ON p.id = n.ip_id
+ WHERE netgroup=\"win\" AND n.only=1 AND h.status = 'active'
+ """)
+ winmachines.__add__(list(cursor.fetchall()))
+ hostslpdfile = header
for machine in redmachines:
- self.filedata['hosts.lpd'] += machine + "\n"
- self.filedata['hosts.lpd'] += "\n"
+ hostslpdfile += machine[0] + "\n"
+ hostslpdfile += "\n"
for machine in winmachines:
- self.filedata['hosts.lpd'] += machine + "\n"
+ hostslpdfile += machine[0] + "\n"
+ self.filedata['hosts.lpd']
self.Entries['ConfigFile']['/mcs/etc/hosts.lpd'] = self.FetchFile
+
def buildNetgroups(self):
- '''this rebuilds the many different files that will eventually
- get post processed and converted into a ypmap for netgroups'''
+ """Makes the *-machine files"""
header = """###################################################################
-# This file lists hosts in the '%s' machine netgroup, it is
-# automatically generated. DO NOT EDIT THIS FILE! To update
-# the hosts in this file, edit hostbase and do a 'make nets'
-# in /mcs/adm/hostbase.
-#
-# Number of hosts in '%s' machine netgroup: %i
-#\n\n"""
-
- netgroups = {}
- for host in self.xdata['hostbase.xml']:
- if host.find('netgroup').get('netgroup') == "" or host.find('netgroup').get('netgroup')== 'none':
- continue
- if host.find('netgroup').get('netgroup') not in netgroups:
- netgroups.update({host.find('netgroup').get('netgroup') :
- [".".join([host.get('hostname'), host.get('domain')])]})
- else:
- netgroups[host.find('netgroup').get('netgroup')].append(".".join([host.get('hostname'),
- host.get('domain')]))
-
- for name in host.findall('interface/ip/name'):
- if name.get('only') != 'no':
- netgroups[host.find('netgroup').get('netgroup')].append(name.get('name'))
+ # This file lists hosts in the '%s' machine netgroup, it is
+ # automatically generated. DO NOT EDIT THIS FILE! To update
+ # the hosts in this file, edit hostbase and do a 'make nets'
+ # in /mcs/adm/hostbase.
+ #
+ # Number of hosts in '%s' machine netgroup: %i
+ #\n\n"""
+
+ cursor = connection.cursor()
+ # fetches all the hosts that with valid netgroup entries
+ cursor.execute("""
+ SELECT h.hostname, n.name, h.netgroup, n.only FROM ((dbconvert_host h
+ INNER JOIN dbconvert_interface i ON h.id = i.host_id)
+ INNER JOIN dbconvert_ip p ON i.id = p.interface_id)
+ INNER JOIN dbconvert_name n ON p.id = n.ip_id
+ WHERE h.netgroup <> '' AND h.netgroup <> 'none' AND h.status = 'active'
+ ORDER BY h.netgroup, h.hostname
+ """)
+ nameslist = cursor.fetchall()
+ # gets the first host and initializes the hash
+ hostdata = nameslist[0]
+ netgroups = {hostdata[2]:[hostdata[0]]}
+ for row in nameslist:
+ # if new netgroup, create it
+ if row[2] not in netgroups:
+ netgroups.update({row[2]:[]})
+ # if it belongs in the netgroup and has multiple interfaces, put them in
+ if hostdata[0] == row[0] and row[3]:
+ netgroups[row[2]].append(row[1])
+ hostdata = row
+ # if its a new host, write the old one to the hash
+ elif hostdata[0] != row[0]:
+ netgroups[row[2]].append(row[0])
+ hostdata = row
for netgroup in netgroups:
- self.filedata["%s-machines" % netgroup] = header % (netgroup, netgroup, len(netgroups[netgroup]))
- netgroups[netgroup].sort()
+ fileoutput = header % (netgroup, netgroup, len(netgroups[netgroup]))
for each in netgroups[netgroup]:
- self.filedata["%s-machines" % netgroup] += each + "\n"
- self.Entries['ConfigFile']["/var/yp/netgroups/%s-machines" % netgroup] = self.FetchFile
-
- def dumpXML(self):
- '''this just dumps the info in the hostbase.xml file to be used
- with external programs'''
- self.filedata['hostbase.xml'] = self.xdata['hostbase.xml']
- self.Entries['ConfigFile']['/etc/hostbase.xml'] = self.FetchFile
-
+ fileoutput += each + "\n"
+ self.filedata['%s-machines' % netgroup] = fileoutput
+ self.Entries['ConfigFile']['%s-machines' % netgroup] = self.FetchFile