diff --git a/files/diskspreparation.sh b/files/diskspreparation.sh new file mode 100755 index 0000000000000000000000000000000000000000..bf574a847aede99e368a23005ec2dc06000bf45e --- /dev/null +++ b/files/diskspreparation.sh @@ -0,0 +1,366 @@ +#!/usr/bin/env bash + +export DISK_SDA_SCHEME="gpt" +declare -a DISK_SDA_PARTITIONS=() +DISK_SDA_PARTITIONS+=("1GB:fat16:/boot:defaults:0:0:False:boot,esp") +DISK_SDA_PARTITIONS+=("12.5GB:ext4:/:defaults:0:0:True:") +export DISK_SDA_PARTITIONS +export DISK_SDB_SCHEME="mbr" +declare -a DISK_SDB_PARTITIONS=() +DISK_SDB_PARTITIONS+=("12GB:linux-swap::defaults:0:0:true") +export DISK_SDB_PARTITIONS + +declare -a DISK_DEVICES=("sda" "sdb") +export DISK_DEVICES + +# convertSizeToByte - converts a given size to byte +# parameter: +# $1 - size in "kB", "kiB", "MB", "MiB", "GB", "GiB", "TB" or "TiB" +# return: +# size in byte +convertSizeToByte() { + local unit=$(echo $1 | sed "s/[0-9\.]*//g") + local value=$(echo $1 | sed "s/[a-zA-Z%]*//g") + local factor=1 + + case $(echo ${unit} | tr [A-Z] [a-z]) in + "b") factor=1 ;; + "kb") factor=1000 ;; + "mb") factor=1000000 ;; + "gb") factor=1000000000 ;; + "tb") factor=1000000000000 ;; + "kib") factor=1024 ;; + "mib") factor=1048576 ;; + "gib") factor=1073741824 ;; + "tib") factor=1099511627776 ;; + *) factor=1 ;; + esac + + res=$(dc -e "0k ${value} ${factor} * p") + + echo "${res%.*}" +} + +# convertByteToSize - converts a byte size to a given unit +# parameter: +# $1 - size in byte +# $2 - unit like "B", "kB", "kiB", "MB", "MiB", "GB", "GiB", "TB" or "TiB" +# return: +# rounded size with unit +convertByteToSize() { + local factor=1 + + case $(echo $2 | tr [A-Z] [a-z]) in + "b") factor=1 ;; + "kb") factor=1000 ;; + "mb") factor=1000000 ;; + "gb") factor=1000000000 ;; + "tb") factor=1000000000000 ;; + "kib") factor=1024 ;; + "mib") factor=1048576 ;; + "gib") factor=1073741824 ;; + "tib") factor=1099511627776 ;; + *) factor=1 ;; + esac + + res=$(dc -e "2k $1 ${factor} / p") + echo "${res%.*}$2" +} + +# validateDiskScheme - checks the scheme of a disk device +# parameter: +# $1 - disk device name +# return: +# 0 - no differences +# 1 - current label differs from given label +validateScheme() { + local lbl=$(echo ${diskdata[0]} | cut -f 6 -d ":") + local retval=1 + local scheme=$(eval echo \$DISK_$(echo $1 | tr [a-z] [A-Z])_SCHEME) + + if [ "x${scheme}" = "x${lbl}" ]; + then + retval=0 + fi + + return ${retval} +} + +# initialDiskScheme - initials the scheme of a disk device +# parameter: +# $1 - disk device name +# return: +# none +initialDiskScheme() { + local scheme=$(eval echo \$DISK_$(echo $1 | tr [a-z] [A-Z])_SCHEME) + + if [ ${scheme} = "mbr" ]; + then + parted -s -m /dev/$1 mklabel msdos + else + parted -s -m /dev/$1 mklabel ${scheme} + fi + + return +} + +# validateDiskPartitionLayout - checks the partition layout of a disk device +# parameter: +# $1 - disk device name +# return: +# 0 - no differences +# 1 - current partition layout differs from given partition layout +validateDiskPartitionLayout() { + declare -a parts=() + local retval=0 + + for part in $(eval "for p in \${DISK_$(echo $1 | tr [a-z] [A-Z])_PARTITIONS[@]}; do echo \$p; done ") + do + parts+=(${part}) + done + + if [ ${#parts[@]} -eq $((${#diskdata[@]} - 1)) ]; + then + for idx in $(seq 1 1 ${#parts[@]}) + do + gsize=$(convertSizeToByte $(echo ${parts[$((${idx} - 1))]} | cut -f 1 -d ":")) + dsize=$(convertSizeToByte $(echo ${diskdata[${idx}]} | cut -f 4 -d ":")) + diffperc=$(dc -e "2k $dsize $gsize - 100 * $gsize / p" | sed -e "s/^-//g") + + if [ -n "x${diffperc%.*}" ]; + then + diffperc=0 + fi + + #if difference between current disk size and given disk size more than 1% then the partition layout has changed + if [ ${diffperc%.*} -gt 1 ]; + then + retval=1 + fi + done + else + retval=1 + fi + + return ${retval} +} + +# initialDiskPartitionLayout - initial the partition layout of a disk device +# parameter: +# $1 - disk device name +# return: +# none +initialDiskPartitionLayout() { + declare -a parts=() + local scheme=$(eval echo \$DISK_$(echo $1 | tr [a-z] [A-Z])_SCHEME) + local start=$(convertSizeToByte "1MiB") + local fs="" + local size="" + local end="" + local idx=1 + + # create partitions + for part in $(eval "for p in \${DISK_$(echo $1 | tr [a-z] [A-Z])_PARTITIONS[@]}; do echo \$p; done ") + do + fs=$(echo ${part} | cut -f 2 -d ":") + fsize=$(echo ${part} | cut -f 1 -d ":") + size=$(convertSizeToByte $(echo ${part} | cut -f 1 -d ":")) + end=$((${start} + ${size})) + case ${scheme} in + "mbr" | "msdos") + parted -a optimal -s -m /dev/$1 mkpart primary ${fs} $(convertByteToSize ${start} "MiB") $(convertByteToSize ${end} "MiB") + ;; + + "gpt") + parted -a optimal -s -m /dev/$1 mkpart "Part${idx}" ${fs} $(convertByteToSize ${start} "MiB") $(convertByteToSize ${end} "MiB") + ;; + esac + start=${end} + idx=$(($idx + 1)) + done +} + +# setDiskPartitionFlags - set the flags of a disk partitions +# parameter: +# $1 - disk device name +# return: +# none +setDiskPartitionFlags() { + local idx + local flags + + # reset all flags of every partition + for part in $(parted -s -m /dev/$1 print | sed -e "1,2d;s/[\ ;]//g" | cut -f 1,7 -d ":") + do + idx=$(echo ${part} | cut -f 1 -d ":") + for flag in $(echo ${part} | sed "s/^[^:]*:\(.*\)$/\1/g;s/,/ /g") + do + parted -s /dev/$1 set ${idx} ${flag} off + done + done + + # set all given flags of a partition + idx=1 + for part in $(eval "for p in \${DISK_$(echo $1 | tr [a-z] [A-Z])_PARTITIONS[@]}; do echo \$p; done ") + do + flags=$(echo ${part} | cut -f 8 -d ":") + if [ -n "${flags}" ]; + then + for flag in $(echo ${flags} | sed "s/,/ /g") + do + parted -s /dev/$1 set ${idx} ${flag} on + done + fi + idx=$(($idx + 1)) + done + + return +} + +# formatDiskPartion - format a partition +# parameter: +# $1 - disk device name +# $2 - disk partition index +# $3 - filesystem name +# return: +# 0 - no error +# 1 - error occurred +# 2 - unknown filesystem +formatDiskPartion() { + local device="/dev/$1$2" + local retval=0 + + case $(echo $3 | tr "[A-Z]" "[a-z]") in + "ext4") mkfs.ext4 -q -F ${device} >/dev/null|| retval=1 ;; + "ext3") mkfs.ext3 -q -F ${device} >/dev/null || retval=1 ;; + "fat32") mkfs.vfat ${device} >/dev/null || retval=1 ;; + "fat16") mkfs.msdos -F 16 ${device} >/dev/null || retval=1 ;; + "swap") mkswap ${device} >/dev/null || retval=1 ;; + "ntfs") mkntfs -q -f ${device} >/dev/null || retval=1 ;; + "btrfs") mkfs.btrfs -q -f ${device} >/dev/null || retval=1 ;; + "reiserfs") mkreiserfs -q ${device} >/dev/null || retval=1 ;; + *) retval=2 ;; + esac + + return ${retval} +} + +# formatDiskPartitions - format partitions of a disk if necessary +# parameter: +# $1 - disk device name +# return: +# none +formatDiskPartitions() { + declare -a parts=() + local idx + local gfs + local dfs + local format + + for part in $(eval "for p in \${DISK_$(echo $1 | tr [a-z] [A-Z])_PARTITIONS[@]}; do echo \$p; done ") + do + parts+=(${part}) + done + + for part in $(parted -s -m /dev/$1 print | sed -e "1,2d;s/[\ ;]//g" | cut -f 1,5 -d ":") + do + idx=$(echo ${part} | cut -f 1 -d ":") + dfs=$(echo ${part} | cut -f 2 -d ":") + gfs=$(echo ${parts[$((${idx} - 1))]} | cut -f 2 -d ":") + format=$(echo ${parts[$((${idx} - 1))]} | cut -f 7 -d ":" | tr "[A-Z]" "[a-z]") + + if [ "${dfs}" != "${gfs}" -o "${format}" = "true" ]; + then + formatDiskPartion $1 ${idx} ${gfs} + fi + done +} + +# generateFSTab - generate an fstab file +# parameter: +# $1 - path of fstab file +# $2 - mount path prefix (optional) +# return: +# none +generateFSTab() { + local idx + local uuid + local blkidout + local mntpnt + local mntpntpfx="" + local fs + local opts + local dmp + local pass + + if [ $# -eq 2 ]; + then + mntpntpfx="$2" + fi + + echo -e "#device mount point filesystem options dump pass\n" >$1 + + for disk in ${DISK_DEVICES[@]} + do + idx=1 + for part in $(eval "for p in \${DISK_$(echo ${disk} | tr [a-z] [A-Z])_PARTITIONS[@]}; do echo \$p; done ") + do + blkidout=$(blkid /dev/${disk}${idx}) + uuid=$(echo ${blkidout} | sed "s/^.*UUID=\([^\ ]*\).*$/\1/g;s/\"//g") + fs=$(echo ${blkidout} | sed "s/^.*TYPE=\([^\ ]*\).*$/\1/g;s/\"//g") + mntpnt=$(echo ${part} | cut -f 3 -d ":") + opts=$(echo ${part} | cut -f 4 -d ":") + dmp=$(echo ${part} | cut -f 5 -d ":") + pass=$(echo ${part} | cut -f 6 -d ":") + + if [ ${fs} = "swap" -o ${fs} = "linux-swap" ]; + then + mntpnt="none" + fi + + if [ -n ${fs} -a -n ${mntpnt} -a -n ${uuid} ]; + then + echo "#/dev/${disk}${idx}" >>$1 + if [ ${mntpnt} != "none" ]; + then + echo -e "UUID=${uuid} ${mntpntpfx}${mntpnt} ${fs} ${opts} ${dmp} ${pass}\n" >>$1 + else + echo -e "UUID=${uuid} ${mntpnt} ${fs} ${opts} ${dmp} ${pass}\n" >>$1 + fi + fi + idx=$((${idx} + 1)) + done + done +} + +for disk in ${DISK_DEVICES[@]} +do + declare -a diskdata=() + + for ddt in $(parted -s -m /dev/${disk} print 2>/dev/null | sed '1d;s/[ ]*//g') + do + diskdata+=(${ddt}) + done + + validateScheme ${disk} + + if [ $? -eq 0 ]; + then + validateDiskPartitionLayout ${disk} + + if [ $? -ne 0 ]; + then + initialDiskPartitionLayout ${disk} + fi + + else + initialDiskScheme ${disk} + initialDiskPartitionLayout ${disk} + fi + + setDiskPartitionFlags ${disk} + formatDiskPartitions ${disk} +done + +generateFSTab "/tmp/fstab.local" +generateFSTab "/tmp/fstab.target" "/target" diff --git a/tasks/buildinstaller.yml b/tasks/buildinstaller.yml index 50f044fea1fc3985ad7766fb2e63d0f6a06ffef5..f2741233540b47810278e57541d80a415a9b63ba 100644 --- a/tasks/buildinstaller.yml +++ b/tasks/buildinstaller.yml @@ -37,7 +37,9 @@ - {"name": "bootlocal.sh", "mode": "0775" } # - {"name": "genfstab", "mode": "0775"} - {"name": "installer.sh", "mode": "0775"} -# - {"name": "function.sh", "mode": "0775"} + - {"name": "installer.config", "mode": "0755"} + - {"name": "functions.sh", "mode": "0775"} + - {"name": "diskpreperation.sh", "mode": "0775"} loop_control: loop_var: _linux_install_file diff --git a/templates/answerfile.j2 b/templates/answerfile.j2 index 415f2e7f9291d37a00f8a290fb824d7b2bcf8533..fd91c3914e7b3f994f23947a5349b0c6af7e3b4d 100644 --- a/templates/answerfile.j2 +++ b/templates/answerfile.j2 @@ -14,7 +14,7 @@ export TIMEZONE="{{ hostobj.timezone | default("GMT") }}" {% if 'partitions' in disk %} {{ 'declare -a DISK_%s_PARTITIONS=()' | format(disk.device | upper) }} {% for part in disk.partitions %} -{{ 'DISK_%s_PARTITIONS+=("%s:%s:%s:%s:%s:%s:%s")' | format(disk.device | upper, part.size, part.fs, part.mountpoint | default(""), part.mountoptions | default("defaults"), part.dump | default("0"), part.pass | default("0"), part.format | default("true")) }} +{{ 'DISK_%s_PARTITIONS+=("%s;%s;%s;%s;%s;%s;%s;%s")' | format(disk.device | upper, part.size, part.fs, part.mountpoint | default(""), part.mountoptions | default("defaults"), part.dump | default("0"), part.pass | default("0"), part.format | default("true")), (part.flags | default([])) | join(",") }} {% endfor %} {{ 'export DISK_%s_PARTITIONS' | format(disk.device | upper) }} {% endif %} @@ -25,7 +25,7 @@ export DISK_DEVICES {% set netifs = [] %} {% for ifname, ifdata in hostobj.network.devices.items() %} -{% set ifresdata = namespace(ipv4_address = "", ipv4_netmask = "", ipv6_address = "", ipv6_prefix = "") %} +{% set ifresdata = namespace(ipv4_address = "", ipv4_netmask = "", ipv4_prefix = "", ipv6_address = "", ipv6_prefix = "") %} {% if ifdata.ipv4 is defined %} {% if hostobj.network.classes[ifdata.class].dhcp is defined %} {% if hostobj.network.classes[ifdata.class].dhcp.ipv4 is defined %} @@ -34,14 +34,17 @@ export DISK_DEVICES {% else %} {% set ifresdata.ipv4_address = ifdata.ipv4 %} {% set ifresdata.ipv4_netmask = ('%s/%s' | format(ifdata.ipv4, hostobj.network.classes[ifdata.class].ipv4.prefix) | ipaddr('netmask')) %} +{% set ifresdata.ipv4_prefix = hostobj.network.classes[ifdata.class].ipv4.prefix %} {% endif %} {% else %} {% set ifresdata.ipv4_address = ifdata.ipv4 %} {% set ifresdata.ipv4_netmask = ('%s/%s' | format(ifdata.ipv4, hostobj.network.classes[ifdata.class].ipv4.prefix) | ipaddr('netmask')) %} +{% set ifresdata.ipv4_prefix = hostobj.network.classes[ifdata.class].ipv4.prefix %} {% endif %} {% else %} {% set ifresdata.ipv4_address = ifdata.ipv4 %} {% set ifresdata.ipv4_netmask = ('%s/%s' | format(ifdata.ipv4, hostobj.network.classes[ifdata.class].ipv4.prefix) | ipaddr('netmask')) %} +{% set ifresdata.ipv4_prefix = hostobj.network.classes[ifdata.class].ipv4.prefix %} {% endif %} {% endif %} {% if ifdata.ipv6 is defined %} @@ -62,7 +65,7 @@ export DISK_DEVICES {% set ifresdata.ipv6_prefix = hostobj.network.classes[ifdata.class].ipv6.prefix %} {% endif %} {% endif %} -{{ 'export NETIF_%s="%s:%s:%s:%s:%s"' | format(ifname | upper, ifresdata.ipv4_address, ifresdata.ipv4_netmask, ifresdata.ipv6_address, ifresdata.ipv6_prefix, ifdata.static | default("true")) }} +{{ 'export NETIF_%s="%s;%s;%s;%s;%s;%s"' | format(ifname | upper, ifresdata.ipv4_address, ifresdata.ipv4_netmask, ifresdata.ipv4_prefix, ifresdata.ipv6_address, ifresdata.ipv6_prefix, ifdata.static | default("true")) }} {% do netifs.append('"%s"' | format(ifname)) %} {% endfor %} declare -a NETIF_DEVICES=({{ netifs | join(" ") }})