Commit 2a959c47 authored by Nikolai Kristiansen's avatar Nikolai Kristiansen
Browse files

Make it easier setting multiple hosts as pxe installable, ++

parent a07edd16
from mdb.models import *
from django.contrib import admin
from django.contrib import admin, messages
from mdb.models import Ip6Address, Interface, Ip4Address, DhcpOption, DhcpCustomField, DomainSrvRecord, DomainTxtRecord, \
DomainCnameRecord, DomainARecord, Domain, Host, Ip4Subnet, Ip6Subnet, Nameserver, MailExchange, OperatingSystem, \
HostType, DhcpConfig
class Ip6AddressInline(admin.TabularInline):
......@@ -40,6 +43,26 @@ class HostAdmin(admin.ModelAdmin):
# ('kerberos_principal_name', 'kerberos_principal_created_date'))
# }),
actions = ['set_installable']
def _get_host_warning_message(self, host, ifs):
ifs_str = ', '.join([ for _if in ifs])
return 'Host {} might not be installable since interface(s) {} has no IP set.'.format(host, ifs_str)
def set_installable(self, request, queryset):
invalid_ifs_per_host = []
for obj in queryset:
invalid_ifs = obj.interface_set.filter(ip4address__isnull=True)
if invalid_ifs.exists():
invalid_ifs_per_host.append(self._get_host_warning_message(obj, invalid_ifs))
obj.pxe_installable = True # triggers post save signal
if invalid_ifs_per_host:
self.message_user(request, message='\n'.join(invalid_ifs_per_host), level=messages.WARNING)
set_installable.short_description = "Mark selected hosts as PXE installable"
def get_queryset(self, request):
return super(HostAdmin, self).get_queryset(request).select_related()
......@@ -53,12 +53,12 @@ class Domain(models.Model):
def num_records(self):
host_a_records = Host.objects.filter(interface__domain=self).count()
size = {
"cname": self.domaincnamerecord_set.count(),
"srv": self.domainsrvrecord_set.count(),
"txt": self.domaintxtrecord_set.count(),
"a": self.domainarecord_set.count() + host_a_records
"CNAME": self.domaincnamerecord_set.count(),
"SRV": self.domainsrvrecord_set.count(),
"TXT": self.domaintxtrecord_set.count(),
"A": self.domainarecord_set.count() + host_a_records
return size
return ', '.join(['{}: {}'.format(k, v) for k, v in size.items()])
num_records.short_description = "Num Records"
......@@ -526,11 +526,11 @@ class Host(models.Model):
def mac_addresses(self):
addresses = self.interface_set.filter(macaddr__isnull=False).values_list('macaddr', flat=True)
return ",".join(addresses)
return ", ".join(addresses)
def ip_addresses(self):
addresses = self.interface_set.filter(ip4address__isnull=False).values_list('ip4address__address', flat=True)
return ",".join(addresses)
return ", ".join(addresses)
def as_pxe_files(self):
return host_as_pxe_files(self)
......@@ -87,21 +87,40 @@ def update_domain_serial_when_change_to_host(sender, instance, created, **kwargs
@receiver(post_save, sender=Host)
def create_pxe_key_and_write_pxe_files_when_host_changes(sender, instance, created, **kwargs):
if not instance.pxe_key:
host = instance
if not host.pxe_key:
# generate key (prevent infinite recursion by using update)
pxe_key = uuid.uuid4().hex
instance.pxe_key = pxe_key
host.pxe_key = pxe_key
for pxe_file_name, pxe_file in instance.as_pxe_files():
for pxe_file_name, pxe_file in host.as_pxe_files():
path = os.path.join(settings.MDB_PXE_TFTP_ROOT, pxe_file_name)
if instance.pxe_installable:
if host.pxe_installable:
with open(path, 'w+') as f:
f.write(pxe_file)"Created or updated {}".format(path))
# Also set necessary fields for pxe installation
interfaces = host.interface_set.exclude(ip4address__isnull=True)
for _if in interfaces:
changed = False
if not _if.pxe_filename:
_if.pxe_filename = 'pxelinux.0' # don't overwrite
changed = True
if not _if.dhcp_client:
_if.dhcp_client = True
changed = True
if changed:
os.unlink(path)"deleted {}".format(path))
if os.path.exists(path):
os.unlink(path)"deleted {}".format(path))
@receiver(pre_delete, sender=Interface)
......@@ -68,13 +68,12 @@ def get_pxe_filename(interface, filename_format='mac_addr'):
def host_as_pxe_files(host):
""" Returns a list of filename,content for each host """
""" Returns a list of filename,content for each host interface with an IPv4 address """
from mdb.models import Host
assert isinstance(host, Host)
pxe_files = []
ifs = host.interface_set.filter(dhcp_client=True)
for _if in ifs:
for _if in host.interface_set.exclude(ip4address__isnull=True):
filename = get_pxe_filename(_if)
content = render_pxelinux_cfg(_if, host)
pxe_files.append((filename, content))
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