Provisionierung hinzugefügt

This commit is contained in:
Alfred Krohmer 2013-12-08 21:13:48 +01:00
parent ac208d1dc1
commit ad91308b74
18 changed files with 410 additions and 0 deletions

20
aufgabe4.4/clone.sh Normal file
View File

@ -0,0 +1,20 @@
#!/bin/sh
IP="10.20.0.1"
# our partclone.dd wrapper script to support ext4
cd /usr/sbin
mv partclone.dd partclone.dd-backup
wget http://$IP/pxelinux/scripts/partclone.dd-clone -O partclone.dd
chmod +x partclone.dd
# mount NFS and symlink image folder
mount -t nfs $IP:/cluster /mnt
rm -rf /home/partimag
ln -s /mnt/images /home/partimag
# save image and umount NFS afterwards
ocs-sr -b -p /bin/true -z3 saveparts computenode sda1 sda3
umount /mnt
bash

124
aufgabe4.4/cluster Executable file
View File

@ -0,0 +1,124 @@
#!/bin/bash
function valid_ip()
{
local ip=$1
local stat=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
return $stat
}
function valid_mac()
{
local mac=$1
if [[ $mac =~ ^[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}$ ]]; then
return 0
fi
return 1
}
if [ $# -lt 2 ]
then
echo "Usage: $0 add HOSTNAME IP HWADDR | delete HOSTNAME | set-clone HOSTNAME | set-restore HOSTNAME | set-normal HOSTNAME" >&2
exit 1
fi
if [[ $2 = *[[:space:]]* ]]
then
echo "Hostname must not contain whitespaces"
exit 1
fi
HOSTNAME="$2"
if [ "$1" == "status" ]
then
echo -n "$HOSTNAME is booting "
TARGET="`readlink /srv/tftp/pxelinux/pxelinux.cfg/$HOSTNAME`"
if [ "$TARGET" == "/pxelinux.cfg/local" ]
then
echo "from local harddisk"
elif [ "$TARGET" == "/pxelinux.cfg/live" ]; then
echo "to live Clonezilla environment"
elif [ "$TARGET" == "/pxelinux.cfg/clone" ]; then
echo "to Clonezilla to clone its harddisk"
elif [ "$TARGET" == "/pxelinux.cfg/live" ]; then
echo "to Clonezilla to restore its harddisk"
fi
exit 0
fi
if [ "$1" == "add" ]
then
if [ $# -lt 4 ]
then
echo "Missing arguments" >&2
exit 1
fi
if ! valid_ip $3; then
echo "Invalid IP: $3" >&2
exit 1
fi
IP="$3"
if ! valid_mac $4; then
echo "Invalid MAC: $4" >&2
exit 1
fi
HWADDR="$4"
grep -q "include \"/etc/dhcpd.d/$HOSTNAME\";" /etc/dhcpd.d/all || echo "include \"/etc/dhcpd.d/$HOSTNAME\";" >> /etc/dhcpd.d/all
[ -e "/etc/dhcpd.d/$HOSTNAME" ] || cat /etc/dhcpd.client.conf | sed "s/HOSTNAME/$HOSTNAME/g" | sed "s/HWADDR/$HWADDR/g" > "/etc/dhcpd.d/$HOSTNAME"
grep -q "$HOSTNAME A $IP" /var/named/zotac.zone || (echo "$HOSTNAME A $IP" >> /var/named/zotac.zone && rndc reload zotac)
ln -sf /srv/tftp/pxelinux/pxelinux.cfg/default /srv/tftp/pxelinux/pxelinux.cfg/$HOSTNAME
fi
if [ "$1" == "delete" ]
then
rm -f "/etc/dhcpd.d/$HOSTNAME"
sed -i "/include \"\/etc\/dhcpd.d\/$HOSTNAME\";/d" /etc/dhcpd.d/all
sed -i "/$HOSTNAME A $IP/d" /var/named/zotac.zone
rndc reload zotac
rm -f /srv/tftp/pxelinux/pxelinux.cfg/$HOSTNAME
fi
if [ "$1" == "set-live" ]
then
sed -i -E "s/^(\s*)#filename \"\/pxelinux.0\";/\\1filename \"\/pxelinux.0\";/" "/etc/dhcpd.d/$HOSTNAME"
ln -sf /pxelinux.cfg/default /srv/tftp/pxelinux/pxelinux.cfg/$HOSTNAME
fi
if [ "$1" == "set-clone" ]
then
sed -i -E "s/^(\s*)#filename \"\/pxelinux.0\";/\\1filename \"\/pxelinux.0\";/" "/etc/dhcpd.d/$HOSTNAME"
ln -sf /pxelinux.cfg/clone /srv/tftp/pxelinux/pxelinux.cfg/$HOSTNAME
fi
if [ "$1" == "set-restore" ]
then
sed -i -E "s/^(\s*)#filename \"\/pxelinux.0\";/\\1filename \"\/pxelinux.0\";/" "/etc/dhcpd.d/$HOSTNAME"
ln -sf /pxelinux.cfg/restore /srv/tftp/pxelinux/pxelinux.cfg/$HOSTNAME
fi
if [ "$1" == "set-local" ]
then
#sed -i -E "s/^(\s*)filename \"\/pxelinux.0\";/\\1#filename \"\/pxelinux.0\";/" "/etc/dhcpd.d/$HOSTNAME"
ln -sf /pxelinux.cfg/local /srv/tftp/pxelinux/pxelinux.cfg/$HOSTNAME
fi
systemctl restart dhcpd4@eth1

View File

@ -0,0 +1,6 @@
host HOSTNAME {
hardware ethernet HWADDR;
fixed-address HOSTNAME;
option configfile "pxelinux.cfg/HOSTNAME";
#filename "/pxelinux.0";
}

124
aufgabe4.4/dhcpd.conf Normal file
View File

@ -0,0 +1,124 @@
# dhcpd.conf
#
# Sample configuration file for ISC dhcpd
#
# option definitions common to all supported networks...
option domain-name "zotac";
option domain-name-servers zotac0.zotac;
option dhcp-parameter-request-list = concat(option dhcp-parameter-request-list,d1);
option configfile code 209 = text;
use-host-decl-names true;
default-lease-time 43200;
max-lease-time 86400;
# Use this to enble / disable dynamic dns updates globally.
#ddns-update-style none;
# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;
allow booting;
allow bootp;
# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;
# No service will be given on this subnet, but declaring it helps the
# DHCP server to understand the network topology.
subnet 10.20.0.0 netmask 255.255.255.0 {
# range 10.20.0.100 10.20.0.200;
option routers zotac0.zotac;
}
# This is a very basic subnet declaration.
#subnet 10.254.239.0 netmask 255.255.255.224 {
# range 10.254.239.10 10.254.239.20;
# option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
#}
# This declaration allows BOOTP clients to get dynamic addresses,
# which we don't really recommend.
#subnet 10.254.239.32 netmask 255.255.255.224 {
# range dynamic-bootp 10.254.239.40 10.254.239.60;
# option broadcast-address 10.254.239.31;
# option routers rtr-239-32-1.example.org;
#}
# A slightly different configuration for an internal subnet.
#subnet 10.5.5.0 netmask 255.255.255.224 {
# range 10.5.5.26 10.5.5.30;
# option domain-name-servers ns1.internal.example.org;
# option domain-name "internal.example.org";
# option routers 10.5.5.1;
# option broadcast-address 10.5.5.31;
# default-lease-time 600;
# max-lease-time 7200;
#}
# Hosts which require special configuration options can be listed in
# host statements. If no address is specified, the address will be
# allocated dynamically (if possible), but the host-specific information
# will still come from the host declaration.
#host zotac1 {
# hardware ethernet 00:1c:c0:d5:a9:ee;
# fixed-address zotac1.zotac;
# use-host-decl-names true;
# next-server 10.20.0.1;
# filename "/pxelinux.0";
#}
include "/etc/dhcpd.d/all";
#host passacaglia {
# hardware ethernet 0:0:c0:5d:bd:95;
# filename "vmunix.passacaglia";
# server-name "toccata.fugue.com";
#}
# Fixed IP addresses can also be specified for hosts. These addresses
# should not also be listed as being available for dynamic assignment.
# Hosts for which fixed IP addresses have been specified can boot using
# BOOTP or DHCP. Hosts for which no fixed address is specified can only
# be booted with DHCP, unless there is an address range on the subnet
# to which a BOOTP client is connected which has the dynamic-bootp flag
# set.
#host fantasia {
# hardware ethernet 08:00:07:26:c0:a5;
# fixed-address fantasia.fugue.com;
#}
# You can declare a class of clients and then do address allocation
# based on that. The example below shows a case where all clients
# in a certain class get addresses on the 10.17.224/24 subnet, and all
# other clients get addresses on the 10.0.29/24 subnet.
#class "foo" {
# match if substring (option vendor-class-identifier, 0, 4) = "SUNW";
#}
#
#shared-network 224-29 {
# subnet 10.17.224.0 netmask 255.255.255.0 {
# option routers rtr-224.example.org;
# }
# subnet 10.0.29.0 netmask 255.255.255.0 {
# option routers rtr-29.example.org;
# }
# pool {
# allow members of "foo";
# range 10.17.224.10 10.17.224.250;
# }
# pool {
# deny members of "foo";
# range 10.0.29.10 10.0.29.230;
# }
#}

4
aufgabe4.4/dhcpd.d/all Normal file
View File

@ -0,0 +1,4 @@
include "/etc/dhcpd.d/zotac1";
include "/etc/dhcpd.d/zotac2";
include "/etc/dhcpd.d/zotac3";
include "/etc/dhcpd.d/zotac4";

View File

@ -0,0 +1,6 @@
host zotac1 {
hardware ethernet 00:1c:c0:d5:a9:ee;
fixed-address zotac1;
option configfile "pxelinux.cfg/zotac1";
filename "/pxelinux.0";
}

View File

@ -0,0 +1,6 @@
host zotac2 {
hardware ethernet 00:01:2e:2c:91:69;
fixed-address zotac2;
option configfile "pxelinux.cfg/zotac2";
filename "/pxelinux.0";
}

View File

@ -0,0 +1,6 @@
host zotac3 {
hardware ethernet 00:01:2e:2c:82:f1;
fixed-address zotac3;
option configfile "pxelinux.cfg/zotac3";
filename "/pxelinux.0";
}

View File

@ -0,0 +1,6 @@
host zotac4 {
hardware ethernet 00:01:2e:2c:5d:09;
fixed-address zotac4;
option configfile "pxelinux.cfg/zotac4";
filename "/pxelinux.0";
}

View File

@ -0,0 +1,3 @@
#!/bin/bash
exec /usr/sbin/partclone.ext4 -c "$@"

View File

@ -0,0 +1,3 @@
#!/bin/bash
exec /usr/sbin/partclone.ext4 -r "$@"

View File

@ -0,0 +1,3 @@
label Clonezilla-live
MENU LABEL Clonezilla Live (Ramdisk)
DEFAULT vmlinuz initrd=initrd.img boot=live config noswap nolocales edd=on nomodeset ocs_prerun1="wget http://10.20.0.1/pxelinux/scripts/clone.sh -P /tmp" ocs_live_run="bash /tmp/clone.sh" ocs_live_extra_param="" keyboard-layouts="de" ocs_live_batch="no" live-getty locales="en_US.UTF-8" vga=788 nosplash noprompt fetch=tftp://10.20.0.1/filesystem.squashfs ethdevice-timeout=120 ocs_daemonon="ssh" usercrypted=h651XdpmWpnEo

View File

@ -0,0 +1,3 @@
label Clonezilla-live
MENU LABEL Clonezilla Live (Ramdisk)
DEFAULT vmlinuz initrd=initrd.img boot=live config noswap nolocales edd=on nomodeset ocs_live_run="bash" ocs_live_extra_param="" keyboard-layouts="de" ocs_live_batch="no" live-getty locales="en_US.UTF-8" vga=788 nosplash noprompt fetch=tftp://10.20.0.1/filesystem.squashfs ethdevice-timeout=120 ocs_daemonon="ssh" usercrypted=h651XdpmWpnEo

View File

@ -0,0 +1,5 @@
DEFAULT localboot
label localboot
MENU LABEL localboot
COM32 chain.c32
APPEND hd0

View File

@ -0,0 +1,3 @@
label Clonezilla-live
MENU LABEL Clonezilla Live (Ramdisk)
DEFAULT vmlinuz initrd=initrd.img boot=live config noswap nolocales edd=on nomodeset ocs_prerun1="wget http://10.20.0.1/pxelinux/scripts/restore.sh -P /tmp" ocs_live_run="bash /tmp/restore.sh" ocs_live_extra_param="" keyboard-layouts="de" ocs_live_batch="no" live-getty locales="en_US.UTF-8" vga=788 nosplash noprompt fetch=tftp://10.20.0.1/filesystem.squashfs ethdevice-timeout=120 ocs_daemonon="ssh" usercrypted=h651XdpmWpnEo

42
aufgabe4.4/restore.sh Normal file
View File

@ -0,0 +1,42 @@
#!/bin/sh
IP="10.20.0.1"
# our partclone.dd wrapper script to support ext4
cd /usr/sbin
mv partclone.dd partclone.dd-backup
wget http://$IP/pxelinux/scripts/partclone.dd-restore -O partclone.dd
chmod +x partclone.dd
# mount NFS and symlink image folder
mount -t nfs $IP:/cluster /mnt
rm -rf /home/partimag
ln -s /mnt/images /home/partimag
# restore image and umount NFS afterwards
ocs-sr -b -p /bin/true -e -g auto restoreparts computenode sda1 sda3
umount /mnt
# mount restored system
mount /dev/sda3 /mnt
mount /dev/sda1 /mnt/boot
mount -o bind /proc /mnt/proc
mount -o bind /dev /mnt/dev
mount -o bind /sys /mnt/sys
# create system specific initrd
chroot /mnt /usr/bin/mkinitcpio -p linux
# create miscellaneous file systems
mkswap -U 72f3bc4e-237f-4737-94fa-fa3e4d598642 /dev/sda2
mkfs.xfs /dev/sda5
xfs_admin -U cf837a59-c7b3-40a9-bf83-20acb6eb0fb8 /dev/sda5
# clean up
umount /mnt/sys
umount /mnt/dev
umount /mnt/proc
umount /mnt/boot
umount /mnt
bash

10
aufgabe4.4/tftpd.service Normal file
View File

@ -0,0 +1,10 @@
[Unit]
Description=hpa's original TFTP daemon
[Service]
Type=forking
ExecStart=/usr/bin/in.tftpd -l -s -vv /srv/tftp/pxelinux
StandardError=journal
[Install]
WantedBy=multi-user.target

View File

@ -1,2 +1,38 @@
\subsection{Provisionierung}
\label{sub:provisionierung}
\subsubsection{Vorbereitung}
\begin{sloppypar}
Wir verwenden Clonezilla um die Provisionierung durchzuführen. Um dieses auf den Computenodes zu booten, haben wir den {\tt in.tftpd}-Server installiert und das Service-File für {\tt systemd} angepasst (siehe {\tt aufgabe4.4/tftpd.service}). Außerdem haben wir die Konfiguration des DHCP-Servers so angepasst, dass nun jeder Compute-Node eine eigene Konfigurationsdatei in {\tt /etc/dhcpd.d/} hat, die jeweils in von {\tt /etc/dhcpd.d/all} inkludiert wird.
Außerdem haben wir ein Script {\tt cluster} geschrieben, mit dem die Computenodes verwaltet werden können. Mit
\begin{lstlisting}
cluster add <HOSTNAME> <IP> <MAC>
\end{lstlisting}
wird ein neuer Node hinzugefügt (DHCP- und DNS-Eintrag). Mit
\begin{lstlisting}
cluster set-<MODE> <HOSTNAME>
\end{lstlisting}
kann der Modus für den nächsten Boot des Nodes festgelegt werden. Hier kann man zwischen {\tt local} (Boot von lokaler Festplatte), {\tt live} (Boot in das Clonezilla Image), {\tt clone} (Clonen nach Boot) und {\tt restore} (Image laden nach Boot) wählen.
Um den Netzwerk-Boot zu ermöglichen, haben wir {\tt pxelinux} unter {\tt /srv/tftp/pxelinux} installiert und konfiguriert. In dieses Verzeichnis haben wir die Dateien {\tt vmlinuz}, {\tt initrd.img} und {\tt filesystem.squashfs} aus der Clonezilla-Live-ISO kopiert, sowie außerdem noch {\tt ldlinux.c32, libcom32.c32, libutil.c32, menu.c32, chain.c32} und {\tt pxelinux.0} aus der {\tt syslinux}-Installation. Die Konfigurationsdateien liegen in {\tt /srv/tftp/pxelinux/pxelinux.cfg}.
\end{sloppypar}
\subsubsection{Provisionierung der Computenodes}
\begin{sloppypar}
Um den Clone-Vorgang zu starten, wir nun mit {\tt sudo cluster set-clone <HOSTNAME>} und anschließendem (Neu-)Starten des Nodes das Clonezilla Live Image gebootet. Dieses holt sich nun vom Headnode ein Script und führt dieses aus. In diesem Script haben wir alle nötigen Befehle eingetragen, um das Clonen vorzubereiten und zu starten (siehe {\tt aufgabe4.4/clone.sh}). Dazu wird per NFS das {\tt /cluster}-Verzeichnis des Headnodes eingebunden und dort im Unterverzeichnis {\tt images} das Image der Festplatte abgelegt. Geclont werden nur die {\tt /}- und die {\tt /boot}-Partition.
Zum Wiederherstellen des Images wird mit {\tt sudo cluster set-restore <HOSTNAME>} wieder der entsprechende Boot-Modus gesetzt und der Node neugestartet. Dort wird nun ein anderes Script vom Headnode geholt (siehe {\tt aufgabe4.4/restore.sh}) und die beiden Partitionen wiederhergestellt. Anschließend werden noch die Swap-Partition und die Daten-Partition für das verteilte Dateisystem neu formatiert und die alten UUIDs gesetzt.
Da Clonezilla bei uns {\tt ext4} irgendwie nicht erkannt hat, hat es, um die Partitionen zu klonen, {\tt partclone.dd} verwendet, was allerdings sehr langsam ist, weil es die komplette Partition klont und freie Blöcke nicht auslässt. Deswegen haben wir zwei kleine Wrapper-Scripts geschrieben, die stattdessen {\tt partclone.ext4} aufrufen. (siehe {\tt aufgabe4.4/partclone.dd-clone} und {\tt partclone.dd-restore})
Da wir in unserem Cluster gemischte Boards haben (Intel und Zotac), mussten wir anschließend außerdem noch das Ziel-Root-Verzeichnis mounten und dort mit {\tt mkinitcpio -p linux} ein neues {\tt initrd} erstellen lassen, damit die entsprechenden richtigen Treiber beim Bootvorgang geladen werden können.
Um die automatische Umbenennung der Netzwerk-Interfaces vorzubeugen, mussten wir außerdem einen Symlink {\tt /etc/udev/rules.d/80-net-name-slot.rules -> /dev/null} erstellen. Dieser verhindert, dass das Ethernet-Interface nicht enpXsY sondern fest eth0 benannt wird.
\end{sloppypar}