add s390 cms setup
authorHarald Hoyer <harald@redhat.com>
Tue, 3 Apr 2012 16:53:30 +0000 (18:53 +0200)
committerHarald Hoyer <harald@redhat.com>
Thu, 5 Apr 2012 11:54:38 +0000 (13:54 +0200)
dracut.spec
modules.d/80cms/cms-write-ifcfg.sh [new file with mode: 0755]
modules.d/80cms/cmsifup.sh [new file with mode: 0755]
modules.d/80cms/cmssetup.sh [new file with mode: 0755]
modules.d/80cms/module-setup.sh [new file with mode: 0755]
modules.d/99base/dracut-lib.sh

index d197173..fa3fa39 100644 (file)
@@ -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 (executable)
index 0000000..6349df3
--- /dev/null
@@ -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 (executable)
index 0000000..6481778
--- /dev/null
@@ -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 (executable)
index 0000000..6aa456c
--- /dev/null
@@ -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 (executable)
index 0000000..5cb5413
--- /dev/null
@@ -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
+}
index 14ae625..cb2e4dc 100755 (executable)
@@ -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