Showing posts with label tftp. Show all posts
Showing posts with label tftp. Show all posts

Tuesday, October 21, 2014

Improving LTSP scripting facility

One thing that has been a pain with LTSP is that the scripts in /usr/share/ltsp/screen.d which control what launches on the thin client are all contained within the build image.  Any change/customization to those scripts then requires a rebuild/redeployment of the image.

I thought why not just use the tftp client to pull the script from the TFTP server instead.  Turns out this is quite easy to do.  I added the following script to the screen.d directory, and called it "tftp" (which was just based on one of the existing init scripts):


#!/bin/sh
#

#full path to file (excluding /var/lib/tftpboot)
filepath=$1
file=`basename $filepath`

if [ -n "$SERVER" ]; then
    script_temp=$(mktemp)
    tftp "$SERVER" -c get ${filepath} $script_temp
    # only execute if it has non-zero size.
    if [ -s "$script_temp" ]; then
        mv "$script_temp" /usr/share/ltsp/screen.d/${file}
        chmod 777 /usr/share/ltsp/screen.d/${file}
        exec /bin/bash /usr/share/ltsp/screen.d/${file}
    else
        rm "$script_temp"
        sleep 15
        exec /bin/bash --login
    fi
fi
Now in lts.conf I can do somthing like:

SCREEN_01 = tftp /ltsp-trusty/amd64/firefox

Now I have built the "/var/lib/tftpboot/ltsp-trusty/amd64/firefox" script on the TFTP server and it can easily/quickly customized as needed.

Here is an example (requires "apt-get install firefox openbox" in the ltsp-chroot image):

#!/bin/sh

. /usr/share/ltsp/screen-x-common

export HOME="${HOME:-/root}" USER="${USER:-root}"
COMMAND="openbox-session"
mkdir -p /root/.config/openbox
echo "/usr/bin/firefox http://somesite.biz" >> /root/.config/openbox/autostart
chmod 755 /root/.config/openbox/autostart

# The following logic is described at the top of xinitrc.
if [ -x /usr/share/ltsp/xinitrc ]; then
    xinit /usr/share/ltsp/xinitrc "$COMMAND" -- "$DISPLAY" "vt${TTY}" $X_ARGS >/dev/null
else
    eval "xinit $COMMAND -- $DISPLAY vt${TTY} $X_ARGS >/dev/null"
fi

if [ $? -ne 0 ]; then
    echo "Xserver failed, falling back to a text shell" >&2
    exec /bin/bash --login
fi

So simple things like having one thin-client launch firefox and another launch NX player, is easy thru lts.conf and script manipulation - no rebuilding of images required (apart from package installation of course).


Ubuntu LTSP for the Enterprise


Ubuntu LTSP (ltsp-server package) provides a very easy and convenient method for deploying a thin-client environment (see ltsp.org), but is centered primarily around one server being the DHCP/TFTP/NBD and image build server.  Being in an enterprise environment, I needed to be able to split these functions in order to deploy thin clients.  The image below depicts what I needed to achieve. Essentially I wanted to have ubuntu 14.04 images served by older release servers, so my "build" server needs to be 14.04.  Plus I wanted to be able to server multiple custom images off the same server(s).  Note:  I have existing DHCP/TFTP and NBD servers - so this post assumes these are already established - If you do not, then the ltsp-server package has everything you need, and this post is kinda moot.


First, on my build server, I did the following:

apt-get install ltsp-server
ltsp-build-client --dist trusty --arch amd64 --base /opt/ltsp-trusty

This builds your base client system, in my case an amd64 architecture ubuntu 14.04 base.  It takes about 20 minutes depending on your Internet connection and system speed.  Then any customizations can be done via ltsp-chroot:

ltsp-chroot -a amd64 -b /opt/ltsp-trusty --mount-package-cache

(more on what I customized in later post)

And to build the image:

ltsp-update-image --base /opt/ltsp-trusty

So what we have now on the build server, is the image in /opt/ltsp-trusty/images called amd64.img and the needed tftpboot files in /var/lib/tftpboot/ltsp.  In very simple terms, we now need to deploy the image "amd64.img" to the NBD server, and the PXE boot environment to the TFTP server, and then tweak configuration files to point to the right places.

NBD server (Network Block Device)

For every different image you want to deploy, you need nbd-server listening on a different port.  I am using inetd to spawn the nbd-server instances.  Here is my inetd.conf, which is configured for 3 images on ports 2000 thru 2002:


2000  stream  tcp nowait  nobody /usr/sbin/tcpd /usr/sbin/nbdrootd /opt/ltsp/images/i386.img
2001  stream  tcp nowait  nobody /usr/sbin/tcpd /usr/sbin/nbdrootd /opt/ltsp-trusty/images/amd64.img
2002  stream  tcp nowait  nobody /usr/sbin/tcpd /usr/sbin/nbdrootd /opt/ltsp-trusty/images/i386.img

The image files have to be accessible directly, so in my case I copied them from my build server.


TFTP server (Trivial File Transfer Protocol)

For every different image, you need a specific PXE environment defined in /var/lib/tftpboot.  In my case I have 3:

/var/lib/tftpboot/ltsp/i386
/var/lib/tftpboot/ltsp-trusty/amd64
/var/lib/tftpboot/ltsp-trusty/i386

These can be copied as is from the same location on the build server - each environment can have its own lts.conf file.

Now, there is some tweaking required in order for the client to grab the correct NBD image.  You need to add nbdroot={ipaddress}:{port} to the kernel boot parameters for any image served by the non-standard 2000 NBD port.  This is done in the pxelinux.cfg/ltsp file - snippet below.


# This file is regenerated when update-kernels runs.
# Do not edit, see /etc/ltsp/update-kernels.conf instead.
default ltsp-NBD
ontimeout ltsp-NBD

# This file is regenerated when update-kernels runs.
# Do not edit, see /etc/ltsp/update-kernels.conf instead.
label ltsp-NBD
menu label LTSP, using NBD
kernel vmlinuz-3.13.0-37-generic
#append ro initrd=initrd.img-3.13.0-37-generic init=/sbin/init-ltsp quiet splash root=/dev/nbd0
append ro initrd=initrd.img-3.13.0-37-generic init=/sbin/init-ltsp nosplash root=/dev/nbd0 nbdroot=192.168.202.4:2001
ipappend 2
DHCP server (Dynamic Host Configuration Protocol)

Your DHCP configuration is key, as it directs the PXE booting client to the correct TFTP server and PXE path.  I use an Etherboot gPXE image served by a local TFTP server to fix issues with older network cards - but you may not need that.  Here is one client config section example:

host webc2 {     hardware ethernet 20:cf:30:6f:0a:9e;
     fixed-address webc2;
     option host-name "webc2";
     if substring (option vendor-class-identifier, 0, 9) = "PXEClient"           {
   if exists user-class and option user-class = "gPXE" {
      next-server 192.168.202.4;
      filename "/ltsp-trusty/i386/pxelinux.0";
   } else { filename "/tftpboot/undionly.kpxe"; }
} else {
  next-server 192.168.202.4;
  filename "/ltsp-trusty/i386/nbi.img";}}

The "next-server" portion points it to the TFTP server and PXE file.

You'll probably notice that in my case, my TFTP server and NBD server are on the same server, but its not necessary.

Anyway, in another post I'll discuss an improvement I made to LTSP to allow better scripting via TFTP.

Friday, November 9, 2012

PXE booting of Webconverger

Webconverger is a great web kiosk tool.  This post briefly explains how to customize it and have it boot over a network (PXE boot).  These instructions apply to Ubuntu servers, but concept is adaptable.

First, download the webconverger ISO - I used version 8.0 since I already had it kicking around.

You need a DHCP server, a TFTP server and an NFS server.  Of course, the workstation has to support PXE booting, and be on the same network as these 3 servers.

You can use one physical machine for all three services, but in my scenario I have two machines, one acts as DHCP server, and the other is both the TFTP and NFS server.

DHCP

Using dhcp3-server.. entry in /etc/dhcp3/dhcpd.conf:

        host temp {
                hardware ethernet 00:14:c2:c4:5f:38;
                fixed-address temp.abc.com;
                option host-name "temp";
                option root-path "192.168.202.4:/tftpboot/webc/";
                if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {
                next-server 192.168.202.4;
                filename "webc/pxelinux.0"; }
        }

 Note:  Here the "next-server" is required to redirect to the TFTP server.. obviously change the MAC and ip addresses according to your workstation and servers.  Be sure to restart your DHCP server.

Ok - thats the easy part..  now you have to prep for the TFTP/NFS server setup:


For PXE booting, you need syslinux, nfs-kernel-server, and tftpd-hpa.

TFTP


First, make root tftpboot directory for webconverger, then mount the ISO and copy files into the root dir:
mkdir -p /var/lib/tftpboot/webc/webconverger/8.0
mount -o loop webc8.iso /mnt
cp -a /mnt/* /var/lib/tftpboot/webc/webconverger/8.0
umount /mnt
cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot/webc
cp /usr/lib/syslinux/vesamenu.c32 /var/lib/tftpboot/webc
mkdir /var/lib/tftpboot/webc/pxelinux.cfg

In /var/lib/tftpboot/webc/pxelinux.cfg create a file called "default" with the following contents:

DEFAULT vesamenu.c32
TIMEOUT 10
ONTIMEOUT wc
PROMPT 0
NOESCAPE 1
MENU BEGIN Webconverger
MENU TITLE Webconverger
        MENU INCLUDE webconverger/webconverger.menu
MENU END
NOTE:  The TIMEOUT 10 is basically allowing no time to show menu.. I just want it booting "wc" entry (ONTIMEOUT wc) - adjust accordingly.

Last thing needed is the file /var/lib/tftpboot/webc/webconverger/webconverger.menu:

# nfsroot ip is pxe server's address
LABEL wc
        MENU LABEL Webconverger 8
        KERNEL /webconverger/8.0/live/vmlinuz
APPEND initrd=/webconverger/8.0/live/initrd.img boot=live config homepage=http://www.google.com hostname=webconverger nonetworking nopersistent quickreboot nomodeset noroot splash username=webc vga=current quiet netboot=nfs nfsroot=192.168.202.4:/var/lib/tftpboot/webc/webconverger/8.0
        TEXT HELP
        Boot Webconverger 8.0
ENDTEXT
NFS

Essentially you just need one entry /etc/exports:
/var/lib/tftpboot/webc *(ro,sync,no_subtree_check)
Then do:  exportfs -a

Workstation

Enter BIOS and configure station to boot from network.

You can customize by workstation, by creating additional entries in pxelinux.cfg..    a file called "01-00-14-c2-c4-5f-38" for example, will be used for workstation with MAC of 00:14:c2:c4:5f:38.  Essentially you just copy the "default" file and adjust the ONTIMEOUT to point to a LABEL in webconverger.menu.