summaryrefslogblamecommitdiffstats
path: root/core/rootfs/rootfs-stage32/data/opt/openslx/scripts/systemd-setup_partitions
blob: 0df6ae4e80aa7bc6a08f86dfb202898db77935af (plain) (tree)
1
2
3
4
5
6
7
8
9

                                        
                                                                               
 
                                           
 

                                                                         
 





                                                                               






                                                                             



                                        
 













                                                                                                

                                      

                     
                                                       

                          
                                                                                               
                          

                                             


            
                                                              
                
                                                                     


                                             
                       

                                   











                                                                                       
                                 
                                           
                                  


                                                

                                           
                                  
                             
                                                                                                                                                                                 

                                  
                                       

                                  
                                       

                                  

                                                                                  

                  
                




                          
                                        

                         
                                   




                                                                                        
                         




                                               
                                   





                                     
                  

                          



                                     





                                                           
                                                                                                         
               
                                  
                                                 
                                                                



                                     
                                              


          



                                                 
               
 
                  
                             

  
                
                                                    


                                           
                


                                       
                  


                                                      





                                                      
                    






                                                                                               
                                         

                                                                             
                                                                


                    
                                            


                                                                                                               
 


                                                                          
                                                                                  



                                                                                     





                                                                        
                                                                                  
                                                      
                                        
                                                                                           
                                                                                   






                                                                         
                                                                  
                                         

                                                                                                     
    

                                                              
                    
                              
                                                                     
                                                                                  
                                  












































                                                                                                                                                                                            
                                                                                 






                                                                                                   
                                                                                                       









                                                                                                                           
          



                                                                                        
                             
                             


                        
                                           





                                                                                                

                                                     




                                                                

                                  


        




                                                                                                 
                                

                                                                               



                                                                      
                                                                                                                     




          
#!/bin/bash
# Arrays etc and $(( )) with big numbers
# -----------------------------------------------------------------------------
#
# Copyright (c) 2018 bwLehrpool-Projektteam
#
# This program/file is free software distributed under the GPL version 2.
# See https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
#
# If you have any feedback please consult https://bwlehrpool.de and
# send your feedback to bwlehrpool@hs-offenburg.de.
#
# General information about bwLehrpool can be found at https://bwlehrpool.de
#
# -----------------------------------------------------------------------------
#
# Local hard disk autodetection script for OpenSLX linux stateless clients,
# detecting swap and special partitions

#############################################################################

# Mount point for persistent scratch partition (type 45)
MOUNT_POINT_45="/opt/openslx/persistent"
PARTITION_FILE="/run/openslx/partitions"
readonly MOUNT_POINT_45 PARTITION_FILE
mkdir -p "/run/openslx"

declare -a TMPFILES
gettmp () {
	local vn file
	for vn in "$@"; do
		file=$(mktemp -p /run/openslx) # since we fiddle around with /tmp in this script
		declare -g "${vn}=${file}"
		TMPFILES+=("$file")
	done
}
delalltmp () {
	rm -f -- "${TMPFILES[@]}"
}
trap delalltmp EXIT

# get_mount_options <fstype> <varname>
get_mount_options () {
	case "$1" in
		ext2)
			declare -ag "${2}=(-o nocheck)"
			;;
		ext4)
			declare -ag "${2}=(-o 'errors=remount-ro,data=ordered,relatime,quota')"
			;;
		*)
			declare -ag "${2}=()"
	esac
}

# General formatter for the /tmp partition on a local harddisk
format_disk () {
	declare -ag MOUNT_OPTIONS_SET_BY_FORMAT_DISK=() # Global var!
	local target="$1"
	local fslist="xfs jfs ext3 ext2 ext4"
	local fs
	declare -a fopt
	[ $# -ge 2 ] && fslist="$2"
	for fs in $fslist ; do
		if grep -q "\\b${fs}\\b" "/proc/filesystems"; then
			# Filesystem already supported by running kernel
			:
		elif modprobe "${fs}"; then
			# Filesystem module could be loaded and should be supported now
			:
		else
			# Not supported, try next one
			continue
		fi
		if which "mkfs.$fs" ; then
			case "$fs" in
			reiserfs)
				fopt=("-f")
				;;
			xfs)
				fopt=("-f" "-K")
				;;
			ext2|ext3)
				fopt=("-F")
				;;
			ext4)
				fopt=(-F -b 4096 -O "extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize,quota" -E "nodiscard,quotatype=usrquota:prjquota" -I 256)
				;;
			jfs)
				fopt=()
				;;
			*)
				fopt=()
				;;
			esac
			get_mount_options "$fs" MOUNT_OPTIONS_SET_BY_FORMAT_DISK
			"mkfs.$fs" "${fopt[@]}" "${target}" && return 0 # Success!
		fi
	done
	return 1
}

mount_temp () {
	local PRE=$(pwd)
	if ! cd /tmp; then
		mount_temp_fallback "$@"
		return $?
	fi
	mount "$@" /tmp || return 1
	chmod a+rwxt /tmp
	# Move stuff from working directory, which is old /tmp, to new /tmp just mounted
	mv ./* ./.[!.]* ./..?* /tmp/ 2> /dev/null
	local OLD=$(LANG=C ls -alh | grep -v -E ' \.\.?$' | grep -v '^total')
	[ -n "$OLD" ] && echo -- "Leftovers:" && echo -- "$OLD"
	cd "$PRE" || true
}

mount_temp_fallback () {
	mkdir -p /tmptmp
	mv /tmp/* /tmp/.* /tmptmp/ 2> /dev/null
	mount "$@" /tmp || return 1
	chmod a+rwxt /tmp
	mv /tmptmp/* /tmptmp/.* /tmp/
	rmdir /tmptmp
	return 0
}

wait_for_udev () {
	local upid ctr hdd
	hdd=
	if [ "x$1" = "x--hdd" ]; then
		hdd=true
		shift
	fi
	ctr=$(( "$1" * 10 ))
	if ! [ "$ctr" -gt 0 ]; then # Negation to catch NaN
		ctr=1
	fi
	udevadm trigger &
	usleep 20000 # 20ms
	udevadm settle &> /dev/null & # --timeout doesn't work reliably, sometimes the process just hangs
	upid=$!
	while [ "$ctr" -gt 0 ]; do
		[ -n "$hdd" ] && has_hdd && break
		[ -z "$hdd" ] && ! [ -d "/proc/$upid" ] && break
		usleep 100000 # 100ms
		ctr=$(( ctr - 1 ))
	done
	if [ -d "/proc/$upid" ]; then
		kill -9 "$upid" &> /dev/null &
	fi
}

has_hdd () {
	[ -n "$( ls -U -1 /dev/disk/by-path/ )" ]
}

wait_for_udev 2

if ! has_hdd; then
	wait_for_udev --hdd 4
fi

shopt -s extglob
for disk in /dev/disk/by-path/!(*-part*|*-usb-*); do
	[ -L "$disk" ] || continue
	fdisk -l "$( readlink -f "$disk" )"
done > "$PARTITION_FILE"
shopt -u extglob
if ! [ -s "$PARTITION_FILE" ]; then
	echo "none" > "$PARTITION_FILE"
fi
echo "Partitions:"
cat "$PARTITION_FILE"

# Get all partitions with given id (list of /dev/sdXX)
# Works for MBR/DOS by looking at the type (1 byte)
# and for GPT by looking for the label 'OpenSLX-ID$1'
# in case an id was given, or just at the UUID if some
# longer string was given
# The output will be a list of matching devices,
# sorted from largest to smallest
get_all_with_id () {
	local ID dev exp
	exp=
	while [ $# -gt 0 ]; do
		ID=$1
		shift
		[ -z "$ID" ] && continue
		[ ${#ID} -eq 1 ] && ID="0?$ID" # passed '7' as argument -- look for 0x7 or 0x07
		if [ ${#ID} -le 3 ]; then
			exp="$exp|ID_PART_ENTRY_(NAME=OpenSLX-ID|TYPE=0x)$ID"
		else
			exp="$exp|ID_PART_ENTRY_(TYPE|UUID)=$ID"
		fi
	done
	exp=${exp:1}
	#echo "Partition find is '$exp'" >&2
	for dev in $(find /dev/ -type b); do
		udevadm info --name="$dev" | grep -iqE "($exp)\$" && echo "$(blockdev --getsize64 "$dev") $dev"
	done | sort -n -k1 -r | cut -d' ' -f2
}

# Check for standard swap partitions and make them available to the system
HAVE_SWAP=no
for PART_DEV in $(get_all_with_id "82" "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f"); do
	if swapon "$PART_DEV" -p 10; then
		HAVE_SWAP=yes # low priority, in case we have zram swap, prefer that)
		echo -e "$PART_DEV\tswap\t\tswap\t\tdefaults\t 0 0" >> "/etc/fstab"
	fi
done

# We use special non assigned partition type (id44) for harddisk scratch
# space, thus no normal filesystem will be incidentally deleted or
# corrupted
HAVE_TEMP=no
for PART_DEV in $(get_all_with_id "44" "87f86132-ff94-4987-b250-444444444444"); do
	# check for supported filesystem and formatter
	if format_disk "$PART_DEV"; then
		mount_temp "${MOUNT_OPTIONS_SET_BY_FORMAT_DISK[@]}" "$PART_DEV" || continue
		echo -e "${PART_DEV}\t/tmp\t\tauto\t\tnoexec\t 0 0" >> "/etc/fstab"
		HAVE_TEMP=yes
		break
	else
		echo "formatting failed for some reason"
	fi # Made this non-forking, systemd should handle it - 2013-05-28
done

# Put detected linux partitions (83) into /etc/fstab with "noauto"
for PART_DEV in $(get_all_with_id 83); do
	mkdir -p "/media/${PART_DEV#/dev/*}"
	echo -e "${PART_DEV}\t/media/${PART_DEV#/dev/*}\tauto\t\tnoauto,noexec\t 0 0" >> "/etc/fstab"
done

# special partition 45 (persistent scratch) to $MOUNT_POINT_45
HAVE_PARTITION_45=no
get_mount_options "ext4" mopts
# try all the ID45 partitions until one succeeds, from large to small
for PART_DEV in $(get_all_with_id "45" "87f86132-ff94-4987-b250-454545454545"); do
	mkdir -p "$MOUNT_POINT_45"
	# Let's see if this is an ext4 partition and if so, whether it has the proper size
	# Any fixing should happen first
	gettmp "logfile"
	COUNT=0
	while true; do
		[ "$COUNT" -ge 4 ] && break
		let COUNT++
		fsck.ext4 -y "$PART_DEV" &> "$logfile"
		RET=$?
		if [ "$(( RET & 7 ))" = 4 ]; then
			slxlog "partition-45-fsck" "Error fixing file system errors on ID45 partition" "$logfile"
			break
		fi
		[ "$(( RET & 3 ))" != 1 ] && break
	done
	# awk script to take block count and block size from dumpe2fs output and multiply them to get byte size
	fs_size=$(dumpe2fs -h "$PART_DEV" | awk -F: 'BEGIN{a=0;b=0}{if ($1 == "Block count") a=$2; if($1 == "Block size") b=$2;}END{ if (a>0 && b>0) print a*b}')
	echo "$PART_DEV has ext4 fs of size $fs_size"
	if [ -n "$fs_size" ] && [ "$fs_size" -gt 1000000 ]; then
		# It's ext4, see if partition size was changed offline
		dev_size=$(blockdev --getsize64 "$PART_DEV")
		echo "$PART_DEV has actual size of $dev_size"
		if [ -n "$dev_size" ] && [ "$dev_size" -gt 1000000 ]; then
			# somewhat sane, see what to do
			dev_mb=$(( dev_size / 1024 / 1024 ))
			fs_mb=$(( fs_size / 1024 / 1024 ))
			echo "Dev: $dev_mb, fs: $fs_mb"
			if [ "$(( fs_mb + 100 ))" -lt "$dev_mb" ]; then
				# dev size plus 100MB is still smaller than reported fs size -- resize fs
				gettmp "logfile"
				fsck.ext4 -f -y "$PART_DEV" &> "$logfile"
				if resize2fs "$PART_DEV" &>> "$logfile"; then
					slxlog "partition-45-resize-ok" "Resized partition $PART_DEV from $fs_mb MiB to $dev_mb MiB" "$logfile"
				else
					slxlog "partition-45-resize-fail" "Could not enlarge file system size of $PART_DEV from $fs_mb MiB to $dev_mb MiB" "$logfile"
					dd if=/dev/zero of="$PART_DEV" bs=1M count=1 &>/dev/null
				fi
			elif [ "$dev_size" -lt "$fs_size" ]; then
				# partition is smaller than expected by fs -- killall
				slxlog "partition-45-shrink" "$PART_DEV has ext4 file system which is $fs_mb MiB, but partition size is only $dev_mb MiB. Will wipe partition to be safe..."
				dd if=/dev/zero of="$PART_DEV" bs=1M count=1 &>/dev/null
			fi
		fi
	fi
	# try to mount
	if ! mount -v -t ext4 "${mopts[@]}" "${PART_DEV}" "$MOUNT_POINT_45"; then
		# failed, try to format
		gettmp "logfile"
		if ! format_disk "$PART_DEV" "ext4" &> "$logfile"; then
			slxlog "partition-45-format" "Cannot format $PART_DEV with ext4" "$logfile"
			continue
		fi
		gettmp "logfile"
		if ! mount -v -t ext4 "${mopts[@]}" "${PART_DEV}" "$MOUNT_POINT_45" &> "$logfile"; then
			slxlog "partition-45-newmount" "Cannot mount $PART_DEV with ext4 right after formatting" "$logfile"
			continue
		fi
	fi
	# Mount success -- clean up lost+found
	find "${MOUNT_POINT_45}/slx_lost+found" -mindepth 1 -maxdepth 1 -mtime +90 -type d -exec rm -rf -- {} \;
	if [ -d "${MOUNT_POINT_45}/lost+found" ]; then
		touch "${MOUNT_POINT_45}/lost+found"
		mkdir -p "${MOUNT_POINT_45}/slx_lost+found"
		mv -f -- "${MOUNT_POINT_45}/lost+found" "${MOUNT_POINT_45}/slx_lost+found/$(date +%s)_$$-$RANDOM"
	fi
	chmod 0700 "${MOUNT_POINT_45}/slx_lost+found"
	chown 0:0 "${MOUNT_POINT_45}/slx_lost+found"
	# fstab entry
	echo -e "${PART_DEV}\t${MOUNT_POINT_45}\tauto\t\tnoauto\t\t 0 0" >> "/etc/fstab"
	HAVE_PARTITION_45=yes
	break # success, done
done

# and 46 to /media/devXX
for PART_DEV in $(get_all_with_id "46"); do
	mkdir -p "/media/${PART_DEV#/dev/*}"
	#mount -t auto ${PART_DEV} /mnt/media/${PART_DEV#/dev/*} \n\
	#test -d /mnt/media/${PART_DEV#/dev/*}/home && \
	#  ln -sf /media/${PART_DEV#/dev/*} /var/home
	echo -e "${PART_DEV}\t/media/${PART_DEV#/dev/*}\tauto\t\tnoauto\t\t 0 0" >> "/etc/fstab"
done

# finally, prepare the data subdir on persistent part
if [ "$HAVE_PARTITION_45" = "yes" ]; then
	mkdir -p "$MOUNT_POINT_45/data"
	chown root:root "$MOUNT_POINT_45" "$MOUNT_POINT_45/data"
	chmod a+rwxt "$MOUNT_POINT_45/data"
elif [ -d "$MOUNT_POINT_45" ]; then
	rm -f -- "$MOUNT_POINT_45"
fi

mount -a

# Make tmpfs if nothing could be mounted for /tmp
# 2016-10-12: Use a sane size of 66% which should be generous enough and prevent the machine from
# just crashing if RAM is too full. We previously hugely oversized since vmware wants at least as
# much free space as the VMs RAM; however, this requirement can be disabled with a vmx setting,
# which we're now doing.
if [ "$HAVE_TEMP" = "no" ]; then
	mount_temp -t tmpfs -o size=66% none
	slxlog "partition-temp" "Running /tmp on tmpfs only!" "$PARTITION_FILE"
fi
if [ "$HAVE_SWAP" = "no" ]; then
	TOTAL_RAM=$(grep ^MemTotal /proc/meminfo | awk '{print $2}')
	if [ -n "$TOTAL_RAM" ] && [ "$TOTAL_RAM" -lt "3000000" ]; then
		slxlog "partition-swap" "Have no (formatted) swap partition, using zram swap only!" "$PARTITION_FILE"
	fi
fi

exit 0