From b80078af39f0bebc419a9728eb4d1ab1c36e3579 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Tue, 3 Apr 2012 18:53:30 +0200 Subject: [PATCH] add s390 cms setup --- dracut.spec | 1 + modules.d/80cms/cms-write-ifcfg.sh | 104 ++++++++++++++++++++ modules.d/80cms/cmsifup.sh | 41 ++++++++ modules.d/80cms/cmssetup.sh | 196 +++++++++++++++++++++++++++++++++++++ modules.d/80cms/module-setup.sh | 40 ++++++++ modules.d/99base/dracut-lib.sh | 5 +- 6 files changed, 385 insertions(+), 2 deletions(-) create mode 100755 modules.d/80cms/cms-write-ifcfg.sh create mode 100755 modules.d/80cms/cmsifup.sh create mode 100755 modules.d/80cms/cmssetup.sh create mode 100755 modules.d/80cms/module-setup.sh diff --git a/dracut.spec b/dracut.spec index d197173..fa3fa39 100644 --- a/dracut.spec +++ b/dracut.spec @@ -250,6 +250,7 @@ rm -rf $RPM_BUILD_ROOT %{dracutlibdir}/modules.d/30convertfs %{dracutlibdir}/modules.d/45url-lib %{dracutlibdir}/modules.d/50plymouth +%{dracutlibdir}/modules.d/80cms %{dracutlibdir}/modules.d/90btrfs %{dracutlibdir}/modules.d/90crypt %{dracutlibdir}/modules.d/90dm diff --git a/modules.d/80cms/cms-write-ifcfg.sh b/modules.d/80cms/cms-write-ifcfg.sh new file mode 100755 index 0000000..6349df3 --- /dev/null +++ b/modules.d/80cms/cms-write-ifcfg.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +mkdir -m 0755 -p /run/initramfs/state/etc/sysconfig/network-scripts + +function cms_write_config() +{ + . /tmp/cms.conf + OLDIFS=$IFS + IFS=, + read -a subch_array <<< "indexzero,$SUBCHANNELS" + IFS=$OLDIFS + devbusid=${subch_array[1]} + if [ "$NETTYPE" = "ctc" ]; then + driver="ctcm" + else + driver=$NETTYPE + fi + + DEVICE=$(cd /sys/devices/${driver}/$devbusid/net/ && set -- * && [ "$1" != "*" ] && echo $1) + + uuid=$(cat /proc/sys/kernel/random/uuid) + + IFCFGFILE=/run/initramfs/state/etc/sysconfig/network-scripts/ifcfg-$DEVICE + + strstr "$IPADDR" '*:*:*' && ipv6=1 + +# to please NetworkManager on startup in loader before loader reconfigures net + cat > /etc/sysconfig/network << EOF +HOSTNAME=$HOSTNAME +EOF + if [ "$ipv6" ]; then + echo "NETWORKING_IPV6=yes" >> /etc/sysconfig/network + else + echo "NETWORKING=yes" >> /etc/sysconfig/network + fi + + cat > $IFCFGFILE << EOF +DEVICE=$DEVICE +UUID=$uuid +ONBOOT=yes +BOOTPROTO=static +MTU=$MTU +SUBCHANNELS=$SUBCHANNELS +EOF + if [ "$ipv6" ]; then + cat >> $IFCFGFILE << EOF +IPV6INIT=yes +IPV6_AUTOCONF=no +IPV6ADDR=$IPADDR/$NETMASK +IPV6_DEFAULTGW=$GATEWAY +EOF + else + cat >> $IFCFGFILE << EOF +IPADDR=$IPADDR +NETMASK=$NETMASK +BROADCAST=$BROADCAST +GATEWAY=$GATEWAY +EOF + fi + if [ "$ipv6" ]; then + DNS1=$(set -- ${DNS/,/ }; echo $1) + DNS2=$(set -- ${DNS/,/ }; echo $2) + else + DNS1=$(set -- ${DNS/:/ }; echo $1) + DNS2=$(set -- ${DNS/:/ }; echo $2) + fi +# real DNS config for NetworkManager to generate /etc/resolv.conf + [ "$DNS1" != "" ] && echo "DNS1=$DNS1" >> $IFCFGFILE + [ "$DNS2" != "" ] && echo "DNS2=$DNS2" >> $IFCFGFILE +# just to please loader's readNetInfo && writeEnabledNetInfo +# which eats DNS1,DNS2,... and generates it themselves based on DNS + if [ "$ipv6" ]; then + [ "$DNS" != "" ] && echo "DNS=\"$DNS\"" >> $IFCFGFILE + else + [ "$DNS" != "" ] && echo "DNS=\"${DNS/:/,}\"" >> $IFCFGFILE + fi +# colons in SEARCHDNS already replaced with spaces above for /etc/resolv.conf + [ "$SEARCHDNS" != "" ] && echo "DOMAIN=\"$SEARCHDNS\"" >> $IFCFGFILE + [ "$NETTYPE" != "" ] && echo "NETTYPE=$NETTYPE" >> $IFCFGFILE + [ "$PEERID" != "" ] && echo "PEERID=$PEERID" >> $IFCFGFILE + [ "$PORTNAME" != "" ] && echo "PORTNAME=$PORTNAME" >> $IFCFGFILE + [ "$CTCPROT" != "" ] && echo "CTCPROT=$CTCPROT" >> $IFCFGFILE + [ "$MACADDR" != "" ] && echo "MACADDR=$MACADDR" >> $IFCFGFILE + optstr="" + for option in LAYER2 PORTNO; do + [ -z "${!option}" ] && continue + [ -n "$optstr" ] && optstr=${optstr}" " + optstr=${optstr}$(echo ${option} | tr [[:upper:]] [[:lower:]])"="${!option} + done +# write single quotes since network.py removes double quotes but we need quotes + echo "OPTIONS='$optstr'" >> $IFCFGFILE + unset option + unset optstr + unset DNS1 + unset DNS2 + echo "files /etc/sysconfig/network-scripts" >> /run/initramfs/rwtab + echo "files /var/lib/dhclient" >> /run/initramfs/rwtab +} + +[ -f /tmp/cms.conf ] && cms_write_config diff --git a/modules.d/80cms/cmsifup.sh b/modules.d/80cms/cmsifup.sh new file mode 100755 index 0000000..6481778 --- /dev/null +++ b/modules.d/80cms/cmsifup.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +DEVICE=$1 + +. /tmp/cms.conf + +strstr "$IPADDR" '*:*:*' && ipv6=1 + +if [ "$ipv6" ] && ! str_starts "$IPADDR" "["; then + IPADDR="[$IPADDR]" +fi + +if [ "$ipv6" ] && ! str_starts "$GATEWAY" "["; then + GATEWAY="[$GATEWAY]" +fi + +if [ "$ipv6" ]; then + DNS1=$(set -- ${DNS/,/ }; echo $1) + DNS2=$(set -- ${DNS/,/ }; echo $2) +else + DNS1=$(set -- ${DNS/:/ }; echo $1) + DNS2=$(set -- ${DNS/:/ }; echo $2) +fi + +{ + echo "ip=$IPADDR::$GATEWAY:$NETMASK:$HOSTNAME:$DEVICE:none:$MACADDR" + for i in $DNS1 $DNS2; do + echo "nameserver=$i" + done +} > /etc/cmdline.d/80-cms.conf +unset CMDLINE + +[ -e "/tmp/net.ifaces" ] && read IFACES < /tmp/net.ifaces +IFACES="$IFACES $DEVICE" +echo "$IFACES" >> /tmp/net.ifaces + +ifup $DEVICE -m diff --git a/modules.d/80cms/cmssetup.sh b/modules.d/80cms/cmssetup.sh new file mode 100755 index 0000000..6aa456c --- /dev/null +++ b/modules.d/80cms/cmssetup.sh @@ -0,0 +1,196 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +function sysecho () { + file=$1 + shift + local i=1 + while [ $i -le 10 ] ; do + if [ ! -f "$file" ]; then + sleep 1 + i=$((i+1)) + else + break + fi + done + [ -f "$file" ] && echo $* > $file +} + +function dasd_settle() { + local dasd_status=/sys/bus/ccw/devices/$1/status + if [ ! -f $dasd_status ]; then + return 1 + fi + local i=1 + while [ $i -le 60 ] ; do + local status + read status < $dasd_status + case $status in + online|unformatted) + return 0 ;; + *) + sleep 0.1 + i=$((i+1)) ;; + esac + done + return 1 +} + +function dasd_settle_all() { + for dasdccw in $(while read line; do echo ${line%%(*}; done < /proc/dasd/devices) ; do + if ! dasd_settle $dasdccw ; then + echo $"Could not access DASD $dasdccw in time" + return 1 + fi + done + return 0 +} + +# prints a canonocalized device bus ID for a given devno of any format +function canonicalize_devno() +{ + case ${#1} in + 3) echo "0.0.0${1}" ;; + 4) echo "0.0.${1}" ;; + *) echo "${1}" ;; + esac + return 0 +} + +# read file from CMS and write it to /tmp +function readcmsfile() # $1=dasdport $2=filename +{ + local dev + local numcpus + local devname + local ret=0 + if [ $# -ne 2 ]; then return; fi + # precondition: udevd created dasda block device node + if ! dasd_cio_free -d $1 ; then + echo $"DASD $1 could not be cleared from device blacklist" + return 1 + fi + + modprobe dasd_mod dasd=$CMSDASD + modprobe dasd_eckd_mod + udevadm settle + + # precondition: dasd_eckd_mod driver incl. dependencies loaded, + # dasd_mod must be loaded without setting any DASD online + dev=$(canonicalize_devno $1) + numcpus=$( + while read line; do + if strstr "$line" "# processors"; then + echo ${line##*:}; + break; + fi; + done < /proc/cpuinfo + ) + + if [ ${numcpus} -eq 1 ]; then + echo 1 > /sys/bus/ccw/devices/$dev/online + else + if ! sysecho /sys/bus/ccw/devices/$dev/online 1; then + echo $"DASD $dev could not be set online" + return 1 + fi + udevadm settle + if ! dasd_settle $dev ; then + echo $"Could not access DASD $dev in time" + return 1 + fi + fi + + udevadm settle + + devname=$(cd /sys/bus/ccw/devices/$dev/block; set -- *; [ -b /dev/$1 ] && echo $1) + devname=${devname:-dasda} + + [[ -d /mnt ]] || mkdir /mnt + if cmsfs-fuse --to=UTF-8 -a /dev/$devname /mnt; then + cat /mnt/$2 > /run/initramfs/$2 + umount /mnt || umount -l /mnt + udevadm settle + else + echo $"Could not read conf file $2 on CMS DASD $1." + ret=1 + fi + + if ! sysecho /sys/bus/ccw/devices/$dev/online 0; then + echo $"DASD $dev could not be set offline again" + #return 1 + fi + udevadm settle + + # unbind all dasds to unload the dasd modules for a clean start + ( cd /sys/bus/ccw/drivers/dasd-eckd; for i in *.*; do echo $i > unbind;done) + udevadm settle + modprobe -r dasd_eckd_mod + udevadm settle + modprobe -r dasd_diag_mod + udevadm settle + modprobe -r dasd_mod + udevadm settle + return $ret +} + +processcmsfile() +{ + source /tmp/cms.conf + + if [[ $NETTYPE ]]; then + ( + echo -n $NETTYPE,$SUBCHANNELS + [[ $PORTNAME ]] && echo ",portname=$PORTNAME" + [[ $LAYER2 ]] && echo ",layer2=$LAYER" + [[ "$NETTYPE" = "ctc" ]] && [[ $CTCPROT ]] && echo ",protocol=$CTCPROT" + echo + ) >> /etc/ccw.conf + + OLDIFS=$IFS + IFS=, + read -a subch_array <<< "indexzero,$SUBCHANNELS" + IFS=$OLDIFS + devbusid=${subch_array[1]} + if [ "$NETTYPE" = "ctc" ]; then + driver="ctcm" + else + driver=$NETTYPE + fi + + printf 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="%s", KERNELS=="%s", ENV{INTERFACE}=="?*", RUN+="/sbin/initqueue --onetime --unique --name cmsifup-$env{INTERFACE} /sbin/cmsifup $env{INTERFACE}"\n' "$driver" "$devbusid" > /etc/udev/rules.d/99-cms.rules + [[ -f /etc/udev/rules.d/60-net.rules ]] \ + || printf 'SUBSYSTEM=="net", ACTION=="online", RUN+="/sbin/initqueue --onetime --env netif=$env{INTERFACE} source_hook initqueue/online"\n' >> /etc/udev/rules.d/99-cms.rules + + znet_cio_free + fi + + if [[ $DASD ]]; then + echo $DASD >> /etc/dasd.conf + echo "options dasd_mod dasd=$DASD" >> /etc/modprobe.d/dasd_mod.conf + dasd_cio_free + fi + + unset _do_zfcp + for i in ${!FCP_*}; do + echo "${!i}" >> /etc/zfcp.conf + _do_zfcp=1 + done + [[ $_do_zfcp ]] && zfcp_cio_free + unset _do_zfcp +} + +[[ $CMSDASD ]] || CMSDASD=$(getarg "CMSDASD=") +[[ $CMSCONFFILE ]] || CMSCONFFILE=$(getarg "CMSCONFFILE=") + +# Parse configuration +if [ -n "$CMSDASD" -a -n "$CMSCONFFILE" ]; then + if readcmsfile $CMSDASD $CMSCONFFILE; then + ln -s /run/initramfs/$CMSCONFFILE /tmp/$CMSCONFFILE + ln -s /run/initramfs/$CMSCONFFILE /tmp/cms.conf + processcmsfile + fi +fi diff --git a/modules.d/80cms/module-setup.sh b/modules.d/80cms/module-setup.sh new file mode 100755 index 0000000..5cb5413 --- /dev/null +++ b/modules.d/80cms/module-setup.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +check() { + arch=$(uname -m) + [ "$arch" = "s390" -o "$arch" = "s390x" ] || return 1 + return 255 +} + +depends() { + arch=$(uname -m) + [ "$arch" = "s390" -o "$arch" = "s390x" ] || return 1 + echo znet zfcp dasd dasd_mod + return 0 +} + +installkernel() { + instmods zfcp +} + +install() { + inst_hook pre-trigger 30 "$moddir/cmssetup.sh" + inst_hook pre-pivot 95 "$moddir/cms-write-ifcfg.sh" + inst "$moddir/cmsifup.sh" /sbin/cmsifup + inst /etc/cmsfs-fuse/filetypes.conf + inst /etc/udev/rules.d/99-fuse.rules + inst /etc/fuse.conf + + for file in $(rpm -ql s390utils-base); do + [[ -f $file ]] && inst $file + done + + for file in {"$usrlibdir","$libdir"}/gconv/*; do + [[ -f $file ]] && inst $file + done +#inst /usr/lib/locale/locale-archive + + dracut_install cmsfs-fuse fusermount ulockmgr_server bash tr insmod rmmod cat +} diff --git a/modules.d/99base/dracut-lib.sh b/modules.d/99base/dracut-lib.sh index 14ae625..cb2e4dc 100755 --- a/modules.d/99base/dracut-lib.sh +++ b/modules.d/99base/dracut-lib.sh @@ -383,9 +383,10 @@ ismounted() { wait_for_if_up() { local cnt=0 + local li while [ $cnt -lt 200 ]; do - li=$(ip link show $1) - [ -z "${li##*state UP*}" ] && return 0 + li=$(ip -o link show up dev $1) + [ -n "$li" ] && return 0 sleep 0.1 cnt=$(($cnt+1)) done -- 2.7.4