Tuesday, August 9, 2016

Adding PXE support to Dnsmasq

Untitled Document.md

Overview

Expanding upon my previous post I will set up Dnsmasq to provide PXE services for my lab environment.

Installing syslinux

The first step is to copy the relevant syslinux files into my already existing /tftpboot directory. Since my primary use case with PXE is to boot esxi hypervisors, I’ll need syslinux version 3.86 (evidently later versions are not compatible with mboot.c32 included with esxi).

cd /tmp
wget https://www.kernel.org/pub/linux/utils/boot/syslinux/3.xx/syslinux-3.86.tar.gz
tar xzvf syslinux-3.86.tar.gz
cp /tmp/syslinux-3.86/core/pxelinux.0 /tftpboot/
cp /tmp/syslinux-3.86/memdisk/memdisk /tftpboot/
cp /tmp/syslinux-3.86/com32/menu/menu.c32 /tftpboot/
cd

Now I can create a basic PXE menu. To start, my menu will do nothing but boot local disk.

mkdir /tftpboot/pxelinux.cfg
cat > /tftpboot/pxelinux.cfg/default << EOF
DEFAULT menu.c32
PROMPT 0
TIMEOUT 300
ONTIMEOUT local

MENU TITLE PXE Server

LABEL local
MENU LABEL Boot local hard drive
LOCALBOOT 0

EOF

I can now append additional entries to the menu in order to support booting other operating systems.

Configuring an iPXE boot image

One use case I have in the lab is to perform an inital boot of a VM with the iPXE ISO image. I then use iPXE to bootstrap other images to the VM. For this, I’ll need to prepare the PXE server to serve up the iPXE image.

Grab the iPXE ISO image.

cd /tftpboot
wget http://boot.ipxe.org/ipxe.iso
cd

Add a PXE menu entry for ipxe.

cat >> /tftpboot/pxelinux.cfg/default << EOF
LABEL ipxe
MENU LABEL ipxe
linux memdisk
initrd ipxe.iso
append iso raw

EOF

Done. You should now be able to PXE boot an iPXE image… as odd as that sounds.

Configuring an esxi boot image

Another use case I have in the lab is the ability to kickstart physical hypervisors with esxi. For this, I’ll enable an esxi boot image with support for a kickstart file to automate the install.

Download the ISO image for esxi to /tmp of the CoreOS machine. For ease of scripting later on, store the esxi ISO file name in a variable. Adjust this per your exact version.

ESX_ISO=VMware-VMvisor-Installer-6.0.0-3620759.x86_64.iso

Mount the ISO and copy the files to /tftpboot, modifying the boot.cfg file to reflect the local directory structure.

mkdir /mnt/iso
mount /tmp/${ESX_ISO} /mnt/iso/
mkdir /tftpboot/esxi
rsync -a /mnt/iso/ /tftpboot/esxi
cat /mnt/iso/boot.cfg | sed -e "s#/##g" -e "3s#^#prefix=esxi\n#" > /tftpboot/esxi/boot.cfg
umount /mnt/iso

Add a PXE menu entry for esxi with support for a kickstart file. My environment listens on the interface mgmt0 port 8080, so change the MGMT_IF and HTTP_PORT variables below per your environment.

MGMT_IF=mgmt0
HTTP_PORT=8080
MGMT_IP=$(ip -o -4 addr show ${MGMT_IF} | awk '{print $4}' | cut -d/ -f1)

cat >> /tftpboot/pxelinux.cfg/default << EOF
LABEL esxi
MENU LABEL esxi
kernel esxi/mboot.c32
append -c esxi/boot.cfg ks=http://${MGMT_IP}:${HTTP_PORT}/esxi/kickstart.cfg
ipappend 2

EOF

Create the kickstart file. This assumes a working http server (as per this post).

mkdir /var/www/esxi
touch /var/www/esxi/kickstart.cfg

Edit /var/www/esxi/kickstart.cfg to look as below. Replace ‘aValidLicenseHere’ in the last line with an actual license, otherwise remove the line entirely. Also, replace the value of ‘rootpw’ with your own password.

accepteula
install --firstdisk --overwritevmfs
rootpw VMware1!
reboot

%include /tmp/networkconfig
%pre --interpreter=busybox

# extract network info from bootup
VMK_IF="vmk0"
VMK_NET=$(localcli network ip interface ipv4 get | grep "${VMK_IF}")
VMK_IP=$(echo "${VMK_NET}" | awk '{print $2}')
VMK_NETMASK=$(echo "${VMK_NET}" | awk '{print $3}')
GATEWAY=$(esxcfg-route | awk '{print $5}')
DNS=$(localcli network ip dns server list | grep 'DNS Servers' | awk '{print $3}'| cut -d, -f1)
HOSTNAME=$(nslookup "${VMK_IP}" | grep Address | grep "${VMK_IP}" | awk '{print $4}')

echo "network --bootproto=static --addvmportgroup=true --device=vmnic0 --ip=${VMK_IP} --netmask=${VMK_NETMASK} --gateway=${GATEWAY} --nameserver=${DNS} --hostname=${HOSTNAME}" > /tmp/networkconfig

%firstboot --interpreter=busybox

vim-cmd hostsvc/enable_ssh
vim-cmd hostsvc/start_ssh
vim-cmd hostsvc/enable_nest_shell
vim-cmd hostsvc/start_nest_shell
nestcli system settings advanced set -o /UserVars/SuppressShellWarning -i 1
vim-cmd vimsvc/license --set aValidLicenseHere

You should now be able to PXE boot esxi within the environment.