File: init.drbl

package info (click to toggle)
drbl 5.7.12-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,988 kB
  • sloc: sh: 43,522; perl: 8,820; xml: 867; makefile: 131
file content (403 lines) | stat: -rwxr-xr-x 15,358 bytes parent folder | download
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
#!/bin/bash
# This file is borrowed from Debian's diskless.
# Modified by Steven Shiau <steven _at_ clonezilla org>, Ceasar Sun <ceasar _at_ nchc org tw>
# License: GPL
# 2006/02/28
# Thanks to James MacLean for providing clientdir method in kernel cmdline.
# it looks like:
# append initrd=initrd-pxe.img ramdisk_size=12288 devfs=nomount drblthincli=off selinux=0 clientdir=images

#
DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"

# Append a default search path.
PATH="$PATH:/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:$DRBL_SCRIPT_PATH/sbin:$DRBL_SCRIPT_PATH/bin"
export PATH

# NFS opt for /etc, /var, /usr, /opt..
nfs_ver_opt="nfsvers=3"
# If need, you can add "rsize=65536,wsize=65536"
RO_NFS_EXTRA_OPT="ro,tcp,nolock,$nfs_ver_opt"
RW_NFS_EXTRA_OPT="rw,tcp,nolock,$nfs_ver_opt"

# This param nosharecache is for Kernel 2.6.23 (some in kernel 2.6.22 in Fedora) or later... Kernel 2.6.23 or later will detect the nfs mounting parameters are the same or not for mounting point and sub-tree mouting point. If not, it will exit unless nosharecache is added. See "man 5 nfs" or https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=251655 for more details.
NFS_OPT_TO_ADD="nosharecache"

# Flag to have tmpfs /run or not. This value will be enabled by drblpush if /run is found as tmpfs mounted on DRBL server.
TMPFS_RUN="true"

#
create_dev(){
   # Forget the devfs, we create it by ourself...
   echo -n "Unmounting the old dev if it exists... "
   umount -l /dev 2>/dev/null
   echo "done!"

   if ! mount -n -o size=10240k,mode=0755 -t devtmpfs devtmpfs /dev; then
      echo "W: devtmpfs not available, falling back to tmpfs for /dev"
      mount -n -t tmpfs -o nr_inodes=24576 -o mode=0755 udev /dev
      [ -e /dev/console ] || mknod -m 0600 /dev/console c 5 1
      [ -e /dev/null ] || mknod /dev/null c 1 3
   fi

   echo -n "Creating dev... "
   # Note! We put dev.tgz as the first priority so that if necessary, such MDK 10, we can force to use dev.tgz instead of udev. (Since in MDK10, there is /usr/sbin/udev, but no /usr/sbin/udevstart or /usr/sbin)
   if [ -f /etc/diskless-image/dev.tgz ]; then
     # the option "m" to make sure the time will NOT be extracted, it will use
     # the time now, so that we can avoid the wrong clock or timezone.
     echo -n "Using old-style dev instead of udev... " 
     tar -xzmf /etc/diskless-image/dev.tgz -C /dev
   elif [ -n "$(ls /usr/sbin/udev* /usr/bin/udev* 2>/dev/null)" ]; then
     echo -n "Mounting sysfs... "
     mount -n -t sysfs none /sys
     ln -snf /proc/self/fd /dev/fd
     ln -snf /proc/self/fd/0 /dev/stdin
     ln -snf /proc/self/fd/1 /dev/stdout
     ln -snf /proc/self/fd/2 /dev/stderr
     ln -snf /proc/kcore /dev/core
     [ -d /dev/pts ] || mkdir -m 0755 /dev/pts
     [ -d /dev/shm ] || mkdir -m 1777 /dev/shm
     echo -n "Using udev... " 
     # http://www.redhat.com/archives/rhl-devel-list/2006-April/msg00785.html
     # * Thu Apr 13 2006 Harald Hoyer <harald redhat com> - 089-1
     # - version 089
     # - start_udev uses udevtrigger now instead of udevstart 
     # From FC12, it's udevadm trigger
     udevadm trigger

     # Create console, null, since in FC5, udevstart won't create them.
     [ ! -e /dev/console ] && mknod -m 600 /dev/console c 5 1
     [ ! -e /dev/null ] && mknod -m 666 /dev/null c 1 3
   else
     echo "Failed to create the dev filesystem!"
     echo "System will not be able to function!"
     echo "Program terminated!"
     exit 1
   fi
   echo "done!"
} # end of create_dev()
#
do_nfs_mount() {
  local nfs_src="$1"
  local mnt_point="$2"
  local nfs_opt="$3"
  local nfs_opt_try="$4"
  local flag
  flag="0"
  # Ex: mount -t nfs -n -o $RW_NFS_EXTRA_OPT $nfsserver:$nfshostsdir/$IP/etc /etc 2>/dev/null
  mount -t nfs -n -o $nfs_opt $nfs_src $mnt_point 2>/dev/null
  if [ "$?" -gt 0 ]; then
    echo -n "Try to mount with option \"$NFS_OPT_TO_ADD\"... "
    # Ex: mount -t nfs -n -o $RW_NFS_EXTRA_OPT,$NFS_OPT_TO_ADD $nfsserver:$nfshostsdir/$IP/etc /etc
    mount -t nfs -n -o $nfs_opt,$nfs_opt_try $nfs_src $mnt_point
    [ "$?" -eq 0 ] && flag="1"
  fi
  return $flag
} # end of do_nfs_mount
#
add_extra_nfs_opt_to_fstab() {
  echo "Try to add $NFS_OPT_TO_ADD in /etc/fstab..."
  if [ -z "$(grep -Ew "nosharecache" /etc/fstab)" ]; then
    # Make it like:
    # 192.168.130.254:/tftpboot/nodes/192.168.130.1/etc      /etc    nfs     rw,rsize=65536,wsize=65536,tcp,nosharecache,defaults        0 0
    perl -pi -e "s|(^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+:.*[[:space:]]+.*nfs.*)(,defaults.*)|\$1,nosharecache\$2|g" /etc/fstab
  fi
} # end of add_extra_nfs_opt_to_fstab
#
remove_extra_nfs_opt_to_fstab() {
  echo "Try to remove $NFS_OPT_TO_ADD in /etc/fstab..."
  if [ -n "$(grep -Ew "nosharecache" /etc/fstab)" ]; then
    # Make it like:
    # 192.168.130.254:/tftpboot/nodes/192.168.130.1/etc      /etc    nfs     rw,rsize=65536,wsize=65536,tcp,defaults        0 0
    perl -pi -e "s|,nosharecache||g" /etc/fstab
  fi
} # end of remove_extra_nfs_opt_to_fstab() {
maybe_break(){
	# Refer from Debian live-boot
	if echo "${break:-}" | grep -E -q "(,|^)$1(,|$)"; then
		if command -v chvt >/dev/null 2>&1; then
			chvt 1
		fi

		echo "break point=$break"

		#run_scripts /scripts/panic
		for i in 1 2 3 4 5 6; do
			[ -c /dev/tty$i ] || mknod /dev/tty$i c 4 $i
		done
		REASON="$@" PS1='(init.drbl) ' /bin/sh -i </dev/console >/dev/console 2>&1
	fi
}
parse_cmd_append(){
for x in $(cat /proc/cmdline); do
	case $x in
	break=*)
		break=${x#break=}
		;;
	esac
done

}

############
### MAIN ###
############
# Don't do anything special if computer is already booted
if [ $$ -ne 1 ]; then
   exec /usr/sbin/init $*
   echo "FATAL ERROR: exec /usr/sbin/init failed" >&2
   exit 1
fi

# Don't do anything special if root is rw (ie master system).
if touch /test-rw 2> /dev/null; then
   rm /test-rw
   echo "WARNING: master system installed" >&2
   exec /usr/sbin/init $*
   echo "FATAL ERROR: exec /usr/sbin/init failed" >&2
   exit 1
fi

# Try and find configuration file
if [ ! -f /etc/diskless-image/config ]; then
   echo "ERROR: Cannot find image config file /etc/diskless-image/config!"
   echo "       Not mounting NFS-root directories"
   echo "Program terminated!"
   exit 1
fi

# Load config file
. /etc/diskless-image/config

# To get IP address, we need to mount /proc first
echo -n "Mounting /proc in init... "
mount -n none /proc -t proc
echo "done!"

# Remount the root filesystem read-write.
# For kernel 2.6.18, it seems if root is ro, all the mount later (such as /etc, /var) will be ro.
echo -n "Remounting root filesystem in read-write mode... " 
mount -n -o remount,rw / 2>/dev/null
echo "done!"

# Create the necessary dev files, this should be as early as possible
create_dev

if [ "$TMPFS_RUN" = "true" ]; then
  [ ! -d /run ] && mkdir /run
  mount -t tmpfs -o "nosuid,size=20%,mode=0755" tmpfs /run
  mkdir /run/initramfs
fi

# find my IP address
NETDEVICES="$(LC_ALL=C cat /proc/net/dev | awk -F: '/eth.:|tr.:|p.p.:/{print $1}')"
for DEVICE in $NETDEVICES; do
  # //NOTE// Here we have to use grep "-w" to grep the IPv4 address, avoding getting IPv6 address. 
  # E.g.:
  # eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
  #        inet 192.168.77.254  netmask 255.255.255.0  broadcast 192.168.77.255
  #        inet6 fe80::20c:29ff:fee9:f24e  prefixlen 64  scopeid 0x20<link>
  IP_tmp="$(LC_ALL=C ifconfig $DEVICE | grep -w -A1 $DEVICE | grep -w -v $DEVICE | grep -w "inet" | sed -e 's/addr://'| sed -e 's/^.*inet \([0-9\.]\+\).*$/\1/')"
  if [ -n "$IP_tmp" ]; then
    # Got the IP address, stop to get from other port, so break
    IP=$IP_tmp
    echo "My IP address is $IP ([$DEVICE])."
    break
  fi
done

# Find NFS server
for i in $NFSSERVER_LIST; do
  # Use the clients-of-$nfsserver.txt in the common root.
  if [ -n "$(grep -Ew "$IP" /etc/drbl/clients-of-${i}.txt 2>/dev/null)" ]; then
    nfsserver="$i"
    break 
  fi
done 
if [ -z "$nfsserver" ]; then
  # No NFS server found. Use plan B. Try to use gateway as NFS server
  gateway="$(LANG=C route -n | awk '/^0.0.0.0/ {print $2}')"
  if [ -n "$gateway" ]; then
    nfsserver=$gateway
  else
    echo "NFSSERVER is not found, use default one: \"$nfsserver_default\"."
    nfsserver=$nfsserver_default
  fi
fi

if [ -n "$nfsserver" ]; then
  echo "NFS server is $nfsserver."
else
  echo "No NFS Server was found!"
  echo "Program terminated!"
  exit 1
fi

maybe_break drbl_prenfs

# Check if single system image is on
ssi_flag=0
# For PXE, it's clientdir=node_root in /proc/cmdline, while 
# for GRUB uEFI NB, it's clientdir=\"node_root\"
#(added by function add_opt_in_grub_efi_cfg_block) in /proc/cmdline.
# It should be converted to be clientdir="node_root" by grub, 
# like the cases in the booting of CD or USB flash drive.
# However somehow the GRUB uEFI NB has different behavior.
# Therefore here we have to deal with clientdir=node_root or clientdir=\"node_root\"
clientdir="$(LC_ALL=C grep clientdir /proc/cmdline | sed -e "s/.*clientdir=\([^ ]\+\).*$/\1/" | sed -e 's|\"||g' -e 's|\\||g')"
[ -n "$clientdir" ] && ssi_flag=1

# The flag to modify /etc/fstab
NFS_OPT_TO_ADD_FLAG=0

# client's /etc directory (1) NFS (2) created from a tarball template
if [ "$ssi_flag" = 0 ]; then
  # Normal mode, every client has its own /etc, /var
  echo -en "\\033[0;33m"
  echo "Full DRBL mode: I have my own NFS-based /etc and /var directories."
  echo -en "\\033[0;39m"
  echo -n "Mounting NFS dir /etc... "
  do_nfs_mount $nfsserver:$nfshostsdir/$IP/etc /etc $RW_NFS_EXTRA_OPT $NFS_OPT_TO_ADD
  NFS_OPT_TO_ADD_FLAG=$((NFS_OPT_TO_ADD_FLAG + $?))
  echo "done!"
  echo -n "Mounting NFS dir /var... "
  do_nfs_mount $nfsserver:$nfshostsdir/$IP/var /var $RW_NFS_EXTRA_OPT $NFS_OPT_TO_ADD
  NFS_OPT_TO_ADD_FLAG=$((NFS_OPT_TO_ADD_FLAG + $?))
  echo "done!"
else
  # DRBL SSI mode
  # We need to know if it's in clonezilla box mode (DRBL SSI + runlevel=1)
  # Command "runlevel" in this stage is useless. we have to check by ourself
  # Check if "1" exists in /proc/cmdline
  RL=""
  if grep -qE ".*[[:space:]]+\<1\>([[:space:]]+|$)" /proc/cmdline 2>/dev/null; then
    RL=1
    # It's clonezilla box mode, client does not have to use some graphics
    # setting, expecially large dir like /etc/gconf, /etc/X11, /etc/selinux
    # In RH, we still need an empty directory /etc/X11 for kudzu to write
    # X config,,otherwise kudzu will complain. For Debian, it's not necessary
    # To make it simple, we will create /etc/X11 later.
    ETC_EXCLUDE="--exclude=gconf --exclude=X11 --exclude=selinux"
    echo -en "\\033[0;33m"
    echo "Clonezilla box mode: I use tmpfs /etc and /var, based on tarball templates."
    echo -en "\\033[0;39m"
  else
    # DRBL SSI mode
    echo -en "\\033[0;33m"
    echo "DRBL SSI mode: I use tmpfs /etc and /var, based on tarball templates."
    echo -en "\\033[0;39m"
  fi

  echo -n "Creating one-time-use dir... "
  echo -n "/root... "
  mount -n -t tmpfs -o mode=0700 none /root
  tar -xzmf /drbl_ssi/template_root.tgz -C /
  echo -n "/etc... "
  mount -n -t tmpfs -o mode=0755 none /etc
  tar $ETC_EXCLUDE -xzmf /drbl_ssi/template_etc.tgz -C /
  echo -n "/var... "
  mount -n -t tmpfs -o mode=0755 none /var
  tar -xzmf /drbl_ssi/template_var.tgz -C /
  echo "done!"
fi

# NFS-based /usr is necessary both for normal mode and DRBL SSI mode
echo -n "Mounting NFS dir /usr... "
do_nfs_mount $nfsserver:/usr /usr $RO_NFS_EXTRA_OPT $NFS_OPT_TO_ADD
NFS_OPT_TO_ADD_FLAG=$((NFS_OPT_TO_ADD_FLAG + $?))
echo "done!"

# We have to modify the fstab for DRBL SSI mode (drbl-ssi-client-prepare).
# Perl (used in drbl-ssi-client-prepare) is only available after
# /usr is mounted.
if [ "$ssi_flag" = "1" ]; then
  if [ "$RL" = "1" ]; then
    # In clonezill box mode, to let kudzu shut up, we need /etc/X11 to write X config, since we already use --exclude=X11 to exclude that dir.
    mkdir -p /etc/X11
  else
    # only DRBL SSI mode, not in clonezilla box mode, use NFS
    # We need /var/lib/dpkg or /var/lib/rpm so that later in drbl-ssi-client-prepare, we can use dpkg or rpm to query package to get the GDM_CFG or KDE_CFG
    if [ -d /var/lib/dpkg ]; then
      echo -n "/var/lib/dpkg... "
      do_nfs_mount $nfsserver:/tftpboot/node_root/var/lib/dpkg /var/lib/dpkg $RO_NFS_EXTRA_OPT $NFS_OPT_TO_ADD
      NFS_OPT_TO_ADD_FLAG=$((NFS_OPT_TO_ADD_FLAG + $?))
    elif [ -d /var/lib/rpm ]; then
      echo -n "/var/lib/rpm... "
      do_nfs_mount $nfsserver:/tftpboot/node_root/var/lib/rpm /var/lib/rpm $RO_NFS_EXTRA_OPT 
      NFS_OPT_TO_ADD_FLAG=$((NFS_OPT_TO_ADD_FLAG + $?))
    fi
  fi
  echo "done!"
  drbl-ssi-client-prepare $nfsserver "$RO_NFS_EXTRA_OPT" $RL
fi

# 
if [ "$NFS_OPT_TO_ADD_FLAG" -eq 0 ]; then
  remove_extra_nfs_opt_to_fstab
else
  add_extra_nfs_opt_to_fstab
fi

maybe_break drbl_postnfs

# Clear mtab
rm -f /etc/mtab /etc/mtab~ /etc/mtab~~ /etc/nologin

# systemd v227 forces to have /etc/mtab as symbolic file to /proc/mounts.
# Ref: https://github.com/stevenshiau/drbl/issues/4
## if, for any reason, mtab was not synced with what it should be, Sync it.
#while read ilist; do
#  # skip the "rootfs / rootfs rw 0 0" 
#  [ -n "$(echo $ilist | grep -E "^rootfs \/ rootfs .*")" ] && continue
#  echo $ilist >> /etc/mtab
#done < /proc/mounts
ln -fs /proc/mounts /etc/mtab

# umount the useless /initrd/proc and /initrd if they exist.
for i in /initrd/proc /initrd; do
  if [ -n "$(awk -F " " '{print $2}' /etc/mtab | grep -E "^$i\>")" ]; then
    umount -l $i
  fi
done

# Public IP
if [ -n "$IP" ]; then
  # public ip alias
  if [ -e "/etc/diskless-image/public_ip.drbl" ]; then
    # PUBLIC_IP result is like: 10.231.97.81 netmask 255.255.255.0
    PUBLIC_IP="$(grep -Ew "$IP" /etc/diskless-image/public_ip.drbl | awk '{ print $2" netmask "$3; }')"
    PUBLIC_GW="$(grep -Ew "$IP" /etc/diskless-image/public_ip.drbl | awk '{ print $4; }')"
    if [ -z "$PUBLIC_IP" ]; then
      PUBLIC_IP="$(grep -i -Ew "$HWADDR" /etc/diskless-image/public_ip.drbl | awk '{ print $2" netmask "$3; }')"
      PUBLIC_GW="$(grep -i -Ew "$HWADDR" /etc/diskless-image/public_ip.drbl | awk '{ print $4; }')"
    fi
    
    if [ -n "$PUBLIC_IP" ]; then
      echo "Setting public IP $PUBLIC_IP $GW in $DEVICE:1 by:"
      echo "ifconfig $DEVICE:1 $PUBLIC_IP"
      ifconfig $DEVICE:1 $PUBLIC_IP
      GW="$(route -n | grep -e "^0\.0\.0\.0" | awk '{ print $2; }')"
      route del default gw $GW
      echo "Setting routing table by:"
      echo "route add default gw $PUBLIC_GW dev $DEVICE"
      route add default gw $PUBLIC_GW dev $DEVICE
    fi
  fi
fi

# report success
echo "Done. NFS-root directories are mounted."
echo "Let original init take over..."

# A normal bootparam in /proc/cmdline for clonezilla client is like:
# initrd=initrd-pxe.img devfs=nomount drblthincli=off selinux=0   1 ocs_opt="--language en  -b -g auto -y0 -p true --max-time-to-wait 300 --mcast-port 22 32 multicast_restoredisk 2disks hda hdb"
# We have to filter the ocs_opt to avoid some options, like -b or 1 inside it, which init will think it's emergency mode or other mode
pure_cmdline="$(sed -e "s/ocs_opt=\".*\"//g" /proc/cmdline)"

maybe_break drbl_pre_run_init

# Since /usr is NFS mounted to DRBL server's /usr now. The /usr/sbin/init is the original one.
exec /usr/sbin/init $pure_cmdline $*
# Only should get here if something went wrong
echo "FATAL ERROR: exec /usr/sbin/init failed" >&2
exit 1