Commit 257b00be authored by Nikolai R Kristiansen's avatar Nikolai R Kristiansen
Browse files

feat(pxe): Add support for PXE config per host/os

parent 3659215a
Pipeline #15 skipped
......@@ -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)
......
......@@ -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": "",
......
# -*- 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),
),
]
......@@ -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 + ")"
......
......@@ -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)
......
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)
......
......@@ -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:
......
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