summaryrefslogtreecommitdiffstats
path: root/abs/core-testing/diskless-legacy/config_diskless_frontend.bash
blob: 24d5fc1008f56474685a2abe1f61a86fac5ab749 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
#!/bin/bash
# This script configures your backend so that a diskless
# frontend can boot from it.

function backtitle() { # no arguments.
  BT="${0##*/}"
  KMV='/etc/LinHES-release'
  if [ -f "$KMV" ]; then
    BT="-= $(cat $KMV) $BT =-"
  fi
}

function must_be_root() { # no arguments.
  test $(id -u) == 0 && return
  MSG="\Z1ERROR\Zn: This script \Z4should\Zn be run by \Z1root\Zn."
  dialog --backtitle "$BT" --colors --msgbox "$MSG" 5 45
  exit 4
}

backtitle 
must_be_root

TITLE="Diskless FE Configuration"
DOPTS=(--backtitle "$BT" --title "$TITLE" --trim --aspect 30 )

DAEMON_LOG=/var/log/daemon.log
BOOT_DEFAULT=/tftpboot/pxelinux.cfg/default

unable_to_determine_mac_for_default_fe ()
{
  if dialog "${DOPTS[@]}" --yes-label "Boot FE and try again" \
       --no-label "Delete $fe_nfsroot" \
       --yesno "Unable to automatically determine the MAC address of
       the current default frontend by interrogating $DAEMON_LOG.
       This may be because you have not yet booted the diskless FE. You can
       either boot the diskless FE and try running $0 again, or delete
       $fe_nfsroot and re-create it later." 0 0 ; then
    exit
  else
    rm -Rf $fe_nfsroot $BOOT_DEFAULT
  fi
  exit
}

find_existing_diskless_fes() {

  unset frontend_names
  unset frontend_nfsroots
  unset frontend_ips
  unset frontend_macs

  for frontend_config in $(ls /tftpboot/pxelinux.cfg 2> /dev/null) ; do

    frontend_name=$(basename $(
      grep append /tftpboot/pxelinux.cfg/$frontend_config |
      sed -e 's/.*nfsroot=//' | awk -F, '{print $1}' | awk -F/ '{print $NF}'))
    frontend_nfsroot=$(
      grep append /tftpboot/pxelinux.cfg/$frontend_config |
      cut -d ':' -f 2 | cut -d ',' -f 1)
    frontend_ip=\
$((0x${frontend_config:0:2})).$((0x${frontend_config:2:2})).\
$((0x${frontend_config:4:2})).$((0x${frontend_config:6:2}))
    frontend_mac=$(
      cat /etc/dhcpd.conf |
      grep "host $frontend_name" |
      sed 's/hardware ethernet /#/g' |
      cut -d '#' -f 2 |
      cut -d ';' -f 1)

    if [ -n "$frontend_name" -a -n "$frontend_nfsroot" -a \
         -n "$frontend_ip" -a -n "$frontend_mac" ] ; then
      frontend_names=( "${frontend_names[@]}" $frontend_name )
      frontend_nfsroots=( "${frontend_nfsroots[@]}" $frontend_nfsroot )
      frontend_ips=( "${frontend_ips[@]}" $frontend_ip )
      frontend_macs=( "${frontend_macs[@]}" $frontend_mac )
    fi
  done

echo frontend_names="${frontend_names[@]}"
echo frontend_nfsroots="${frontend_nfsroots[@]}"
echo frontend_ips="${frontend_ips[@]}"
echo frontend_macs="${frontend_macs[@]}"

}

check_for_default_fe () {
  # This function looks to see if there is a diskless FE that has only been
  # partially configured (i.e. it's MAC address has not been determined and
  # as a result it has not been allocated a fixed IP.

  if [ -e $BOOT_DEFAULT ] ; then
      # There is a $BOOT_DEFAULT config file that has not yet been set to a
      # fixed IP address. See if we can interrogate the log files to
      # determine what the MAC adderss of the FE is so that we can turn it
      # into a fixed ip node. This is the first step in allowing multiple
      # diskless frontends.

      # First determine from the default file, the nfsroot that it is for.

      fe_nfsroot=$(grep append $BOOT_DEFAULT | cut -d ':' -f 2 | cut -d ',' -f 1)

      if [ -z "$fe_nfsroot" ] ; then
        echo "Unable to determine the location of the nfsroot from" \
          $BOOT_DEFAULT
        exit
      fi

      echo fe_nfsroot=$fe_nfsroot

      # Now determine the IP address by looking for an instance in the
      # daemon log file for which the specified nfsroot was mounted.

      fe_ipaddress=$(
        grep "authenticated mount request from " $DAEMON_LOG |
        grep $fe_nfsroot |
        tail -1 |
        sed 's/authenticated mount request from /#/g' |
        cut -d '#' -f 2 |
        cut -d ':' -f 1)

      echo fe_ipaddress=$fe_ipaddress

      unset fe_macaddress

      if [ ! -z "$fe_ipaddress" ] ; then
        fe_macaddress=$(
          grep "DHCPACK on $fe_ipaddress" $DAEMON_LOG |
          tail -1 |
          sed 's/DHCPACK on '$fe_ipaddress' to /#/g' |
          cut -d '#' -f 2 |
          cut -d ' ' -f 1)
      fi

      echo fe_macaddress=$fe_macaddress

      if [ -z "$fe_macaddress" ] ; then
        unable_to_determine_mac_for_default_fe
      else
        if ! dialog "${DOPTS[@]}" --yesno "By interrogating $DAEMON_LOG,
                it appears that the $(basename $fe_nfsroot) frontend was
                last used by a host with MAC Address of $fe_macaddress which
                was allocated IP address $fe_ipaddress.
                Do you wish to allocate the IP to that host (so that you
                can configure another diskless FE)?" 0 0 ; then
          dialog "${DOPTS[@]}" --msgbox "Boot the correct diskless FE and
            run $0 again." 0 0
          exit
        fi

        # Setup dhcpd.conf so that the FE's MAC address always uses a fixed
        # ip address and the PXE configuration is fixed for that address.

        hex_ip_address=$(printf "%02X%02X%02X%02X" $(echo $fe_ipaddress |
          tr '.' ' '))
        echo hex_ip_address=$hex_ip_address
        mv -fv $BOOT_DEFAULT $(dirname $BOOT_DEFAULT)/$hex_ip_address

        cp -f /etc/dhcpd.conf /etc/dhcpd.conf.bak
        cat /etc/dhcpd.conf.bak |
          grep -v "host $(basename $fe_nfsroot)" > \
          /etc/dhcpd.conf
        echo "\
host $(basename $fe_nfsroot) \
{hardware ethernet $fe_macaddress; fixed-address $fe_ipaddress;}" \
          >> /etc/dhcpd.conf

        /sbin/sv restart dhcpd

        dialog "${DOPTS[@]}" --msgbox "The frontend $(basename $fe_nfsroot)
          with a MAC address of $fe_macaddress and an nfsroot directory of
          $fe_nfsroot has been configured with a fixed IP address of
          $fe_ipaddress." 0 0
        exit
      fi
  fi

}

get_network_interface() {
  NETDEVICES="$(cat /proc/net/dev |
    awk -F: '/ath.:|wlan.:|eth.:|tr.:/{print $1}')"
  echo NETDEVICES=$NETDEVICES
  NUM_DEVICES=$(echo $NETDEVICES | wc -w)
  echo NUM_DEVICES=$NUM_DEVICES
  if [ $NUM_DEVICES = 1 ] ; then
    INTERFACE=$NETDEVICES
  else
    DEVICELIST=""
    DEVNUM=0
    for DEVICE in $NETDEVICES
    do
      DEVNUM=$(($DEVNUM + 1))
      DEVICELIST="$DEVICELIST $DEVICE Interface${DEVNUM} "
    done
    echo DEVICELIST=$DEVICELIST
    TMP=/tmp/interface
    rm -Rf $TMP
    dialog "${DOPTS[@]}" --menu "Which network interface?" 18 70 12 \
      $DEVICELIST 2>$TMP || exit
    INTERFACE=$(cat $TMP)
  fi
  echo INTERFACE=$INTERFACE
}

validip(){
  echo "$1" | egrep -q -e '[0-9]+\.[0-9]+\.[0-9]+.[0-9]+'
  return $?
}

get_network_info() {
  BACKEND_IP=$(echo $(ifconfig $INTERFACE | grep "inet addr" | tr ':' ' ') |
    cut -d ' ' -f 3)
  echo BACKEND_IP=$BACKEND_IP
  NAMESERVERS="$(awk '/^nameserver/{printf "%s ",$2}' /etc/resolv.conf)"
  echo NAMESERVERS=$NAMESERVERS
  GATEWAY="$(LANG=C LC_ALL=C route -n | awk '/^0\.0\.0\.0/{print $2; exit}')"
  echo GATEWAY=$GATEWAY
  NETWORK="${BACKEND_IP%.*}"
  echo NETWORK=$NETWORK
  HOST="${BACKEND_IP##*.}"
  echo HOST=$HOST
  NETMASK="$(LANG=C LC_ALL=C ifconfig $INTERFACE |
    awk '/[Mm]ask/{FS="[:   ]*";$0=$0; print $8; exit}')"
  echo NETMASK=$NETMASK

  # See if we can determine the range of IP addresses currently allowed in
  # dhcpd.conf

  IPRANGE=( $(grep ^[[:space:]]*range /etc/dhcpd.conf |
              sed 's/range//g' | tr -d ';') )

  echo ${IPRANGE[@]}
  if [ $(echo ${IPRANGE[@]} | wc -w) -eq 2 ] ; then
    START=$(echo ${IPRANGE[0]} | tr '.' '\t' | cut -f 4)
    END=$(echo ${IPRANGE[1]} | tr '.' '\t' | cut -f 4)
    echo START=$START
    echo END=$END
  fi

  # Could not

  if [ -z "$START" -o -z "$END" ] ; then
    if [ "$HOST" -lt "20" ] ; then
      START=21
      END=26
    else
      START=11
      END=16
    fi
  fi

  IPRANGE_FROM=""
  IPRANGE_TO=""

  while [ -z "$IPRANGE_FROM" -o -z "$IPRANGE_TO" -o -z "$IPRANGE" ]
  do
    IPRANGE="$NETWORK.$START $NETWORK.$END"
    rm -f /tmp/iprange

    if ! dialog "${DOPTS[@]}" --clear --inputbox "Please enter the desired
           IP-Range of addresses that should be allocated by clients,
           separated by a single space." 10 75 "$IPRANGE" \
           2> /tmp/iprange ; then
      exit
    fi

    IPRANGE=$(cat /tmp/iprange)
    echo IPRANGE=$IPRANGE
    IPRANGE_FROM="${IPRANGE%% *}"
    IPRANGE_TO="${IPRANGE##* }"

    for i in "$IPRANGE_FROM" "$IPRANGE_TO"
    do
      validip "$i" || IPRANGE=""
    done
  done
}

setup_dhcpd() {
  # Generate dhcpd.conf from template

  if [ ! -f /etc/dhcpd.conf.orig ] ; then
    mv -f /etc/dhcpd.conf /etc/dhcpd.conf.orig
  fi

  ALLNAMESERVERS=""
  for i in $NAMESERVERS; do
    ALLNAMESERVERS="${ALLNAMESERVERS:+$ALLNAMESERVERS,} $i"
  done
  echo ALLNAMESERVERS=$ALLNAMESERVERS

  cat >/etc/dhcpd.conf <<EOT
# dhcpd.conf for LinHES Diskless Frontend

# global settings
## POF allow booting;
allow bootp;
default-lease-time 600;
max-lease-time 7200;

subnet ${NETWORK}.0 netmask ${NETMASK} {
  next-server $BACKEND_IP;
  filename "pxelinux.0";
  option subnet-mask ${NETMASK};
  range ${IPRANGE_FROM} ${IPRANGE_TO};
  ${ALLNAMESERVERS:+option domain-name-servers $ALLNAMESERVERS;}
  ${GATEWAY:+option routers $GATEWAY;}
}
EOT

  for (( fe = 0 ; fe < ${#frontend_names[@]} ; fe++ )) ; do
    echo "host ${frontend_names[$fe]} \
{hardware ethernet ${frontend_macs[$fe]}; \
fixed-address ${frontend_ips[$fe]};}" >> \
      /etc/dhcpd.conf
  done

  /sbin/add_service.sh dhcpd
}

setup_tftpd() {
  /sbin/add_service.sh tftpd
}

check_delete_of_existing_nfsroot() {
  if [ -d $NFSROOT ] ; then
    if dialog "${DOPTS[@]}" --yesno "\
There is already a directory $NFSROOT. Do you want to delete it and \
rebuild it from scratch?" 10 70 ; then
      echo Deleting $NFSROOT
      rm -Rf $NFSROOT
    else
      echo "OK then, bye."
      exit
    fi
  fi
}

enable_mysql_and_backend_networking() {
  # Enable mysql networking on the backend.

  /sbin/sv stop mythbackend

  if grep -q ^skip-networking /etc/my.cnf ; then
    echo "Commenting out skip-networking."
    cp /etc/my.cnf /etc/my.cnf~
    cat /etc/my.cnf~ | sed 's/^skip-networking/#skip-networking/g' > \
      /etc/my.cnf
    /sbin/sv restart mysql
  else
    echo "Already commented out skip-networking."
  fi

  # Make sure that the backend ip settings in the mythtv mysql database have
  # the actual IP address of the backend rather than the loopback address.
  # Otherwise the frontend will not be able to connect to the backend.

  echo "Setting backend IP in mythtv's mysql settings"
  echo "
UPDATE settings SET data='$BACKEND_IP' WHERE value='BackendServerIP';
UPDATE settings SET data='$BACKEND_IP' WHERE value='MasterServerIP';" |
    mysql mythconverg

  /sbin/sv start mythbackend
}

export_mounts() {
  # Ensure that the /myth directory is exported.

  if ! grep -q ^/myth[[:space:]] /etc/exports ; then
    echo "Adding line for /myth in /etc/exports"
    echo "/myth *(rw,async,no_subtree_check)" >> /etc/exports
  else
    echo "Already added line for /myth in /etc/exports"
  fi

  if ! grep -q ^/data/var/cache/pacman[[:space:]] /etc/exports ; then
    echo "Adding line for /data/var/cache/pacman in /etc/exports"
    echo "/data/var/cache/pacman *(rw,async,no_subtree_check)" >> /etc/exports
  else
    echo "Already added line for /data/var/cache/pacman in /etc/exports"
  fi

  # Ensure that the montpoints that are used as storage groups are exported.

  for storage_mount in ${storage_mounts[@]} ; do

    if ! grep -q ^${storage_mount}[[:space:]] /etc/exports ; then
      echo "Adding line for ${storage_mount} in /etc/exports"
      echo "${storage_mount} *(rw,async,no_subtree_check)" >> /etc/exports
    else
      echo "Already added line for ${storage_mount} in /etc/exports"
    fi
  done
}

find_storage_mounts() {
  unset storage_mounts
  for group in $(mysql -sB mythconverg -e \
    "select dirname from storagegroup where hostname = '$(hostname)'") ; do

    group_mount=$group
    while ! mountpoint -q $group_mount ; do
      group_mount=$(dirname $group_mount)
    done

    echo Storage group $group mountpoint is $group_mount
    storage_mounts=( "${storage_mounts[@]}" $group_mount )
  done
}

enable_nfs() {
  /sbin/add_service.sh nfsd
}

restart_nfs (){
  /usr/sbin/exportfs -arv
}

export_nfsroot() {
  # Ensure that the NFSROOT directory is appropriately exported.

  if ! grep -q ^$NFSROOT[[:space:]] /etc/exports ; then
    echo "Adding line for $NFSROOT in /etc/exports"
    echo "$NFSROOT *(rw,no_root_squash,async,no_subtree_check)" >> /etc/exports
  else
    echo "Already added line for $NFSROOT in /etc/exports"
  fi
}

create_tftpboot_directory() {
  # Create the directory with the tftp stuff.

  echo "Creating /tftpboot directories"
  mkdir -p /tftpboot/pxelinux.cfg

  if [ ! -e /tftpboot/pxelinux.0 ] ; then
   cp -fv /usr/lib/syslinux/pxelinux.0 /tftpboot/pxelinux.0
  fi

  if [ ! -e /tftpboot/vmlinuz26 ] ; then
    cp -fv /boot/vmlinuz26 /tftpboot/vmlinuz26
  fi

  if [ ! -e /tftpboot/kernel26.img ] ; then

    echo "Building kernel miniroot"
#    if [ -z "$(awk -F\" '$1 ~ /^MODULES=/ && $2 ~ /nfs/' /etc/mkinitcpio.conf)" ] ; then
#      cp /etc/mkinitcpio.conf /etc/mkinitcpio.conf~
#      sed -e '/^MODULES=/s/\"$/ nfs\"/' < /etc/mkinitcpio.conf~ > /etc/mkinitcpio.conf
#    fi
    if [ -z "$(awk -F\" '$1 ~ /^HOOKS=/ && $2 ~ /net/' /etc/mkinitcpio.conf)" ] ; then
      cp /etc/mkinitcpio.conf /etc/mkinitcpio.conf~
      sed -e '/^HOOKS=/s/\"$/ net\"/' < /etc/mkinitcpio.conf~ > /etc/mkinitcpio.conf
    fi
    /sbin/mkinitcpio -g /tftpboot/kernel26.img
  fi
}

create_default_pxelinux_entry() {
  echo "\
  default linux

  label linux
  kernel vmlinuz26
  append initrd=kernel26.img rootfstype=nfs root=/dev/nfs nfsroot=$BACKEND_IP:$NFSROOT,v3,rsize=16384,wsize=16384 init=/sbin/runit ip=dhcp" \
    > /tftpboot/pxelinux.cfg/default
}

create_new_nfsroot() {
  # Prompt the user for the name of the NFSROOT.

  FRONTEND=
  NFSROOT=

  while [ -z "$FRONTEND" ] ; do
    if ! dialog "${DOPTS[@]}" --inputbox "Enter the hostname of the new
           diskless FE:" 0 0 2> /tmp/frontend_hostname ; then
      exit
    fi

    FRONTEND=$(cat /tmp/frontend_hostname)
  done

  # Prompt the user for the location of the NFSROOT.

  while [ -z "$NFSROOT" ] ; do
    NFSROOT=/nfsroot/$FRONTEND

    if ! dialog "${DOPTS[@]}" --clear --inputbox "Enter the location of the
           NFSROOT for the diskless FE:" \
           0 0 "$NFSROOT" 2> /tmp/nfsroot_location ; then
      exit
    fi

    NFSROOT=$(cat /tmp/nfsroot_location)
  done

  check_delete_of_existing_nfsroot

  # Create the nfsroot directory that the FE will use as its root filesystem.

  echo "Creating the $NFSROOT directory."
  mkdir -p $NFSROOT
  for DIR in /* ; do
    if [[ "$DIR" != /mnt && \
          "$DIR" != /data && \
          "$DIR" != /media && \
          "$DIR" != /tmp && \
          "$DIR" != /etc.old && \
          "$DIR" != /storage && \
          "$DIR" != /var && \
          "$DIR" != /nfsroot && \
          "$DIR" != /tftpboot && \
          "$DIR" != /cdrom ]]
    then
      if mountpoint -q $DIR && [ "$DIR" != "/dev" ] ; then
        echo "  Making mountpoint dir $DIR"
        cd $NFSROOT
        tar c $DIR --exclude=$DIR/* 2> /dev/null | tar x 2> /dev/null
      else
        echo "  Copying $DIR to $NFSROOT"
        cp -ax $DIR $NFSROOT
      fi
    fi
  done

  cd $NFSROOT

  # Exclude specific bits of /var

  tar c /var \
    --exclude=/var/lib/dhcpcd \
    --exclude=/var/lib/locate \
    --exclude=/var/lib/mlocate \
    --exclude=/var/lib/named \
    2> /dev/null | tar x 2> /dev/null

  for DIR in /mnt /data /tmp /media /cdrom /var/lib/mlocate ; do
    echo "  Creating $DIR"
    tar c $DIR --exclude=$DIR/* 2> /dev/null | tar x 2> /dev/null
  done

  mkdir -p $NFSROOT/data/var/cache/pacman

  chroot $NFSROOT /sbin/remove_service.sh dhcpd
  chroot $NFSROOT /sbin/remove_service.sh lighttpd
  chroot $NFSROOT /sbin/remove_service.sh mysql
  chroot $NFSROOT /sbin/remove_service.sh mythbackend
  chroot $NFSROOT /sbin/remove_service.sh nfsd
  chroot $NFSROOT /sbin/remove_service.sh nmbd
  chroot $NFSROOT /sbin/remove_service.sh smbd
  chroot $NFSROOT /sbin/remove_service.sh tftpd
  chroot $NFSROOT /sbin/remove_service.sh avahi

  # Update the fstab.

  cp $NSFROOT/etc/fstab $NFSROOT/etc/fstab~
  cat $NFSROOT/etc/fstab~ | grep -v ext[34] | grep -v xfs |
    grep -v ^UUID= > $NFSROOT/etc/fstab

  echo "\
$BACKEND_IP:/nfsroot / nfs defaults,nolock,auto,noatime 0 2
$BACKEND_IP:/myth /myth nfs defaults,nolock,auto,noatime 0 0
$BACKEND_IP:/data/var/cache/pacman /data/var/cache/pacman nfs defaults,nolock,auto,noatime 0 0
" >> $NFSROOT/etc/fstab

  for storage_mount in ${storage_mounts[@]} ; do
    echo "\
$BACKEND_IP:${storage_mount} ${storage_mount} nfs auto,noatime,nolock,rsize=32768,wsize=32768 0 0" \
    >> $NFSROOT/etc/fstab
  done

  cp $NFSROOT/etc/rc.sysinit $NFSROOT/etc/rc.sysinit~
  sed -e '/^\/sbin\/minilogd/s/$/\n\n# Mount NFS early\n\/bin\/mount -a -t nfs/' \
    < $NFSROOT/etc/rc.sysinit~ > $NFSROOT/etc/rc.sysinit

  # Update networking

  echo $FRONTEND > $NFSROOT/etc/hostname

  cp $NFSROOT/etc/hosts $NFSROOT/etc/hosts~
  echo "127.0.0.1 $FRONTEND localhost" > $NFSROOT/etc/hosts
  cat $NFSROOT/etc/hosts~ | grep -v 127.0.0.1 >> $NFSROOT/etc/hosts

  cp $NFSROOT/etc/net/ifaces/eth0/options $NFSROOT/etc/net/ifaces/eth0/options~
  sed -e 's/^BOOTPROTO=.*/BOOTPROTO=none/' < $NFSROOT/etc/net/ifaces/eth0/options~ \
    > $NFSROOT/etc/net/ifaces/eth0/options

  # Update mysql settings

  cp /usr/share/mythtv/mysql.txt $NFSROOT/home/mythtv/.mythtv/mysql.txt

  if grep -q DBHostName=localhost $NFSROOT/home/mythtv/.mythtv/mysql.txt ; then
    echo "Setting database host in frontend's mysql.txt."
      cp $NFSROOT/home/mythtv/.mythtv/mysql.txt \
         $NFSROOT/home/mythtv/.mythtv/mysql.txt.orig
      cat $NFSROOT/home/mythtv/.mythtv/mysql.txt.orig |
        sed 's/DBHostName=localhost/DBHostName='$BACKEND_IP'/g' > \
        $NFSROOT/home/mythtv/.mythtv/mysql.txt
  else
    echo "Already set Database host in frontend's mysql.txt."
  fi

  chown mythtv:mythtv $NFSROOT/home/mythtv/.mythtv/mysql.txt

  # Check if the user has a diskless_tweak.<frontend_name> file in root's 
  # home directory. If they do, run it inside the chroot of the NFS root.

  if [[ -x ~/diskless_tweak.$FRONTEND ]] ; then
    echo Running tweak file ~/diskless_tweak.$FRONTEND
    chroot $NFSROOT bash -v ~/diskless_tweak.$FRONTEND
  fi

  create_default_pxelinux_entry
  export_nfsroot
  restart_nfs

  dialog "${DOPTS[@]}" --msgbox "Boot your diskless FE
  and then re-run this script ($0) so that the MAC address
  of the Diskless FE can be obtained." 0 0
}

##########################################
##########################################
##
## MAIN BODY OF SCRIPT                  ##
##
##########################################
##########################################

check_for_default_fe
find_existing_diskless_fes

get_network_interface
get_network_info
setup_tftpd
setup_dhcpd
enable_mysql_and_backend_networking
find_storage_mounts
export_mounts
create_tftpboot_directory
enable_nfs

# Restart nfs to ensure that the exported /myth directory can be mounted. This
# is required to create a new frontend.

restart_nfs

if [ ${#frontend_names[@]} -eq 0 ] ; then
  create_new_nfsroot
else
  for (( fe = 0 ; fe < ${#frontend_names[@]} ; fe++ )) ; do
    frontend_options=( "${frontend_options[@]}" \
      "${frontend_names[$fe]} (MAC:${frontend_macs[$fe]} \
IP:${frontend_ips[$fe]})" "" )
  done

echo 0=${frontend_names[0]}
echo 1=${frontend_names[1]}
echo 2=${frontend_names[2]}
echo 3=${frontend_names[3]}

  if ! dialog "${DOPTS[@]}" --menu "Select a frontend to delete or to create
         a new one." 0 0 0 "${frontend_options[@]}" \
         "New Frontend" "" 2> /tmp/selected_fe; then
    exit
  fi

  selected_option=$(cat /tmp/selected_fe)

  if [ "$selected_option" = "New Frontend" ] ; then
    create_new_nfsroot
    exit
  fi

echo $selected_option
echo ${frontend_options[0]}
echo ${frontend_options[2]}
echo ${frontend_nfsroots[@]}

  for (( fe = 0 ; fe < ${#frontend_names[@]} ; fe++ )) ; do
    if [ "$selected_option" = "${frontend_options[$(($fe*2))]}" ] ; then
      if dialog "${DOPTS[@]}" --yesno "Do you wish to delete the frontend
           with nfsroot ${frontend_nfsroots[$fe]}?" 0 0 ; then
        # Delete the nfsroot directory.
        rm -Rfv ${frontend_nfsroots[$fe]}

        # Delete the tftpboot pxe boot config file.

        hex_ip_address=$(printf "%02X%02X%02X%02X" \
          $(echo ${frontend_ips[$fe]} | tr '.' ' '))
        rm /tftpboot/pxelinux.cfg/$hex_ip_address

        # Remove reference to the frontend from the dhcp.conf
        cp -fv /etc/dhcpd.conf /etc/dhcpd.conf.bak
        grep -v "host ${frontend_names[$fe]}" /etc/dhcpd.conf.bak > \
          /etc/dhcpd.conf
        /sbin/sv restart dhcpd
      fi
    fi
  done
fi