From 257b00be1b85b9b5dc95c88536ba213eabde47e0 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Fri, 25 Mar 2016 15:00:25 +0100 Subject: [PATCH] feat(pxe): Add support for PXE config per host/os --- mdb/admin.py | 2 +- mdb/fixtures/test_data.json | 12 ++++++++++ mdb/migrations/0011_auto_20160325_1412.py | 29 +++++++++++++++++++++++ mdb/models.py | 4 ++++ mdb/pxe.py | 21 ++++++++++++---- mdb/tests.py | 26 +++++++++++++++++++- mdbsite/settings.py | 2 ++ 7 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 mdb/migrations/0011_auto_20160325_1412.py diff --git a/mdb/admin.py b/mdb/admin.py index 93e21a1..05801fe 100644 --- a/mdb/admin.py +++ b/mdb/admin.py @@ -192,7 +192,7 @@ class HostTypeAdmin(admin.ModelAdmin): class OperatingSystemAdmin(admin.ModelAdmin): - list_display = ['name', 'version', 'arch'] + list_display = ['name', 'version', 'arch', 'pxe_kernel', 'pxe_initrd', 'pxe_preseed_config_url'] admin.site.register(Domain, DomainAdmin) diff --git a/mdb/fixtures/test_data.json b/mdb/fixtures/test_data.json index 2fc3412..914af75 100644 --- a/mdb/fixtures/test_data.json +++ b/mdb/fixtures/test_data.json @@ -2738,6 +2738,18 @@ "model": "mdb.operatingsystem", "pk": 1 }, +{ + "fields": { + "pxe_initrd": "path-to-initrd-for-os", + "pxe_kernel": "path-to-kernel-for-os", + "pxe_preseed_config_url": "http://url-to-preseed.config", + "arch": "x86_64", + "name": "Ubuntu", + "version": "16.04-beta-final" + }, + "model": "mdb.operatingsystem", + "pk": 2 +}, { "fields": { "kerberos_principal_name": "", diff --git a/mdb/migrations/0011_auto_20160325_1412.py b/mdb/migrations/0011_auto_20160325_1412.py new file mode 100644 index 0000000..00b9cbb --- /dev/null +++ b/mdb/migrations/0011_auto_20160325_1412.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mdb', '0010_auto_20151004_1709'), + ] + + operations = [ + migrations.AddField( + model_name='operatingsystem', + name='pxe_initrd', + field=models.CharField(null=True, blank=True, max_length=255), + ), + migrations.AddField( + model_name='operatingsystem', + name='pxe_kernel', + field=models.CharField(null=True, blank=True, max_length=255), + ), + migrations.AddField( + model_name='operatingsystem', + name='pxe_preseed_config_url', + field=models.URLField(null=True, blank=True), + ), + ] diff --git a/mdb/models.py b/mdb/models.py index d988d4d..adf5ed7 100644 --- a/mdb/models.py +++ b/mdb/models.py @@ -477,6 +477,10 @@ class OperatingSystem(models.Model): version = models.CharField(max_length=64) arch = models.CharField(max_length=255, choices=OS_ARCHITECTURES, blank=True, null=True) + pxe_kernel = models.CharField(max_length=255, blank=True, null=True) + pxe_initrd = models.CharField(max_length=255, blank=True, null=True) + pxe_preseed_config_url = models.URLField(blank=True, null=True) + def __str__(self): return self.name + " " + self.version + " (" + self.arch + ")" diff --git a/mdb/pxe.py b/mdb/pxe.py index 4f1b242..6ac6fe9 100644 --- a/mdb/pxe.py +++ b/mdb/pxe.py @@ -4,11 +4,21 @@ import ipaddress def render_pxelinux_cfg(_if, host): - # TODO add fields to os model and make dynamic per host - distro = 'ubuntu/14_04/amd64/alternate/' - kernel = distro + 'linux' - initrd = distro + 'initrd.gz' + """Renders pxelinux.cfg based on a host and the set of host interfaces. + If the host is tied to an OS with PXE fields set, it will use these instead of defaults.""" + # Default config + kernel = settings.MDB_PXE_KERNEL + initrd = settings.MDB_PXE_INITRD preseed_config_url = settings.MDB_PXE_PRESEED_URL + + # Per host config (via OS model) + _os = host.operating_system + pxe_attrs = [_os.pxe_initrd, _os.pxe_kernel, _os.pxe_preseed_config_url] + if None not in pxe_attrs and '' not in pxe_attrs: + kernel = _os.pxe_kernel + initrd = _os.pxe_initrd + preseed_config_url = _os.pxe_preseed_config_url + context = { 'kernel': kernel, 'initrd': initrd, @@ -16,6 +26,7 @@ def render_pxelinux_cfg(_if, host): 'host': host, 'interface': _if } + return render_to_string('pxelinux.cfg', context=context) @@ -34,7 +45,7 @@ def get_pxe_filename(interface, filename_format='mac_addr'): def host_as_pxe_files(host): - """ Returns a list of filename,content for each host interface with an IPv4 address """ + """Returns a list of filename,content for each host interface with an IPv4 address.""" from mdb.models import Host assert isinstance(host, Host) diff --git a/mdb/tests.py b/mdb/tests.py index 955981f..8a48d96 100644 --- a/mdb/tests.py +++ b/mdb/tests.py @@ -1,12 +1,15 @@ import io + +from django.conf import settings from django.contrib.auth.models import User from django.core.management import call_command from django.core.urlresolvers import reverse from django.test import TestCase +from mdb.pxe import render_pxelinux_cfg from rest_framework.authtoken.models import Token from rest_framework.test import APITestCase -from mdb.models import Host +from mdb.models import Host, OperatingSystem class MyAPITestCases(APITestCase): @@ -35,6 +38,27 @@ class MyAPITestCases(APITestCase): class UnitTests(TestCase): fixtures = ['test_data'] + def test_render_pxeconfig(self): + host = Host.objects.first() + interface = host.interface_set.exclude(ip4address__isnull=True).first() + config = render_pxelinux_cfg(interface, host) + + self.assertIn(settings.MDB_PXE_INITRD, config) + self.assertIn(settings.MDB_PXE_KERNEL, config) + self.assertIn(settings.MDB_PXE_PRESEED_URL, config) + + def test_render_pxeconfig_with_os_pxe_config(self): + _os = OperatingSystem.objects.get(pk=2) # OS with all pxe vars set + Host.objects.filter(pk=Host.objects.first().pk).update(operating_system=_os) + host = Host.objects.first() + + interface = host.interface_set.exclude(ip4address__isnull=True).first() + config = render_pxelinux_cfg(interface, host) + + self.assertIn(_os.pxe_initrd, config) + self.assertIn(_os.pxe_kernel, config) + self.assertIn(_os.pxe_preseed_config_url, config) + def test_host_as_pxe_files(self): host = Host.objects.first() self.assertEqual(len(host.as_pxe_files()), 1) diff --git a/mdbsite/settings.py b/mdbsite/settings.py index bf04d3a..23c99d7 100644 --- a/mdbsite/settings.py +++ b/mdbsite/settings.py @@ -124,6 +124,8 @@ REST_FRAMEWORK = { } MDB_PXE_TFTP_ROOT = '/var/lib/tftpboot/pxelinux/pxelinux.cfg/' +MDB_PXE_KERNEL = 'ubuntu/14_04/amd64/alternate/linux' +MDB_PXE_INITRD = 'ubuntu/14_04/amd64/alternate/initrd.gz' MDB_PXE_PRESEED_URL = 'http://158.36.190.194/ubuntu/preseed_1404.cfg' try: