From 5ae0b92ca434577a47ce00224f5b980eb21eed890b7dfebfdbcac74a2ea19d0d Mon Sep 17 00:00:00 2001 From: Charles Arnold Date: Fri, 25 Sep 2009 21:54:51 +0000 Subject: [PATCH] - bnc#520234 - npiv does not work with XEN Update block-npiv - bnc#496033 - Support for creating NPIV ports without starting vm block-npiv-common.sh block-npiv-vport Update block-npiv - bnc#500043 - Fix access to NPIV disk from HVM vm Update xen-qemu-iscsi-fix.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=20 --- block-npiv | 199 +------------------------------- block-npiv-common.sh | 238 +++++++++++++++++++++++++++++++++++++++ block-npiv-vport | 79 +++++++++++++ xen-qemu-iscsi-fix.patch | 6 +- xen.changes | 8 ++ xen.spec | 6 +- 6 files changed, 333 insertions(+), 203 deletions(-) create mode 100644 block-npiv-common.sh create mode 100644 block-npiv-vport diff --git a/block-npiv b/block-npiv index 34c4792..9f69bac 100644 --- a/block-npiv +++ b/block-npiv @@ -3,209 +3,12 @@ # Usage: block-npiv [add npiv | remove dev] dir=$(dirname "$0") +. "$dir/block-npiv-common.sh" . "$dir/block-common.sh" #set -x #command=$1 -# Look for the NPIV vport with the WWPN -# $1 contains the WWPN (assumes it does not contain a leading "0x") -find_vhost() -{ - unset vhost - - # look in upstream locations - for fchost in /sys/class/fc_vports/* ; do - if test -e $fchost/port_name ; then - wwpn=`cat $fchost/port_name | sed -e s/^0x//` - if test $wwpn = $1 ; then - # Note: makes the assumption the vport will always have an scsi_host child - vhost=`ls -d $fchost/device/host*` - vhost=`basename $vhost` - return - fi - fi - done - - # look in vendor-specific locations - - # Emulex - just looks like another scsi_host - so look at fc_hosts... - for fchost in /sys/class/fc_host/* ; do - if test -e $fchost/port_name ; then - wwpn=`cat $fchost/port_name | sed -e s/^0x//` - if test $wwpn = $1 ; then - # Note: makes the assumption the vport will always have an scsi_host child - vhost=`basename $fchost` - return - fi - fi - done -} - - -# Create a NPIV vport on the fabric w/ FABRICNM, with WWPN,WWNN -# $1 contains FABRICNM -# $2 contains the VPORT WWPN -# $3 contains the VPORT WWNN -# (assumes no name contains a leading "0x") -create_vport() -{ - # find a base adapter with npiv support that is on the right fabric - - # Look via upstream interfaces - for fchost in /sys/class/fc_host/* ; do - if test -e $fchost/vport_create ; then - # is the link up, w/ NPIV support ? - pstate=`cat $fchost/port_state` - ptype=`cat $fchost/port_type | cut -c 1-5` - fname=`cat $fchost/fabric_name | sed -e s/^0x//` - if [ $pstate = "Online" -a $ptype = "NPort" -a $fname = $1 ] ; then - vmax=`cat $fchost/max_npiv_vports` - vinuse=`cat $fchost/npiv_vports_inuse` - avail=`expr $vmax - $vinuse` - if [ $avail -gt 0 ] ; then - # create the vport - echo $2":"$3 > $fchost/vport_create - if [ $? -eq 0 ] ; then - return 0 - fi - # failed - so we'll just look for the next adapter - fi - fi - fi - done - - # Look in vendor-specific locations - - # Emulex: interfaces mirror upstream, but are under adapter scsi_host - for shost in /sys/class/scsi_host/* ; do - if [ -e $shost/vport_create ] ; then - fchost=`ls -d $shost/device/fc_host*` - # is the link up, w/ NPIV support ? - pstate=`cat $fchost/port_state` - ptype=`cat $fchost/port_type | cut -c 1-5` - fname=`cat $fchost/fabric_name | sed -e s/^0x//` - if [ $pstate = "Online" -a $ptype = "NPort" -a $fname = $1 ] ; then - vmax=`cat $shost/max_npiv_vports` - vinuse=`cat $shost/npiv_vports_inuse` - avail=`expr $vmax - $vinuse` - if [ $avail -gt 0 ] ; then - # create the vport - echo $2":"$3 > $shost/vport_create - if [ $? -eq 0 ] ; then - return 0 - fi - # failed - so we'll just look for the next adapter - fi - fi - fi - done - - return 1 -} - - -# Look for the LUN on the indicated scsi_host (which is an NPIV vport) -# $1 is the scsi_host name (normalized to simply the hostX name) -# $2 is the WWPN of the tgt port the lun is on -# Note: this implies we don't support a multipath'd lun, or we -# are explicitly identifying a "path" -# $3 is the LUN number of the scsi device -find_sdev() -{ - unset dev - hostno=${1/*host/} - for sdev in /sys/class/scsi_device/${hostno}:*:$3 ; do - if test -e $sdev/device/../fc_trans*/port_name ; then - tgtwwpn=`cat $sdev/device/../fc_trans*/port_name | sed -e s/^0x//` - if test $tgtwwpn = $2 ; then - if test -e $sdev/device/block* ; then - dev=`readlink $sdev/device/block*` - dev=${dev##*/} - return - fi - fi - fi - done -} - - -# Look for the NPIV vhost based on a scsi "sdX" name -# $1 is the "sdX" name -find_vhost_from_dev() -{ - unset vhost - hostno=`readlink /sys/block/$1/device` - hostno=${hostno##*/} - hostno=${hostno%%:*} - if test -z "$hostno" ; then return; fi - vhost="host"$hostno -} - - -# We're about to terminate a vhost based on a scsi device -# Flush all nodes on that vhost as they are about to go away -# $1 is the vhost -flush_nodes_on_vhost() -{ - if test ! -x /sbin/blockdev ; then return; fi - hostno=${1/*host/} - for sdev in /sys/class/scsi_device/${hostno}:* ; do - if test -e $sdev/device/block* ; then - dev=`readlink $sdev/device/block*` - dev=${dev##*/} - dev="/dev/"$dev - if test -n "$dev"; then - blockdev --flushbufs $dev - fi - fi - done -} - - -# Terminate a NPIV vhost -# $1 is vhost -delete_vhost() -{ - # use upstream interface - for vport in /sys/class/fc_vports/* ; do - if test -e $vport/device/$1 ; then - if test -e $vport/vport_delete ; then - echo "1" > $vport/vport_delete - if test $? -ne 0 ; then exit 6; fi - sleep 4 - return - fi - fi - done - - # use vendor specific interface - - # Emulex - if test -e /sys/class/fc_host/$1/device/../scsi_host*/lpfc_drvr_version ; then - shost=`ls -1d /sys/class/fc_host/$1/device/../scsi_host* | sed s/.*scsi_host://` - vportwwpn=`cat /sys/class/fc_host/$1/port_name | sed s/^0x//` - vportwwnn=`cat /sys/class/fc_host/$1/node_name | sed s/^0x//` - echo "$vportwwpn:$vportwwnn" > /sys/class/scsi_host/$shost/vport_delete - if test $? -ne 0 ; then exit 6; fi - sleep 4 - return - fi - - # Qlogic - if test -e /sys/class/fc_host/$1/device/../scsi_host*/driver_version ; then - shost=`ls -1d /sys/class/fc_host/$1/device/../scsi_host* | sed s/.*scsi_host://` - vportwwpn=`cat /sys/class/fc_host/$1/port_name | sed s/^0x//` - vportwwnn=`cat /sys/class/fc_host/$1/node_name | sed s/^0x//` - echo "$vportwwpn:$vportwwnn" > /sys/class/scsi_host/$shost/vport_delete - if test $? -ne 0 ; then exit 6; fi - sleep 4 - return - fi - - exit 6 -} - case "$command" in add) # Params is one big arg, with fields separated by hyphens: diff --git a/block-npiv-common.sh b/block-npiv-common.sh new file mode 100644 index 0000000..5a3d805 --- /dev/null +++ b/block-npiv-common.sh @@ -0,0 +1,238 @@ + + +# Look for the NPIV vport with the WWPN +# $1 contains the WWPN (assumes it does not contain a leading "0x") +find_vhost() +{ + unset vhost + + # look in upstream locations + for fchost in /sys/class/fc_vports/* ; do + if test -e $fchost/port_name ; then + wwpn=`cat $fchost/port_name | sed -e s/^0x//` + if test $wwpn = $1 ; then + # Note: makes the assumption the vport will always have an scsi_host child + vhost=`ls -d $fchost/device/host*` + vhost=`basename $vhost` + return + fi + fi + done + + # look in vendor-specific locations + + # Emulex - just looks like another scsi_host - so look at fc_hosts... + for fchost in /sys/class/fc_host/* ; do + if test -e $fchost/port_name ; then + wwpn=`cat $fchost/port_name | sed -e s/^0x//` + if test $wwpn = $1 ; then + # Note: makes the assumption the vport will always have an scsi_host child + vhost=`basename $fchost` + return + fi + fi + done +} + + +# Create a NPIV vport on the fabric w/ FABRICNM, with WWPN,WWNN +# $1 contains FABRICNM +# $2 contains the VPORT WWPN +# $3 contains the VPORT WWNN +# (assumes no name contains a leading "0x") +create_vport() +{ + # find a base adapter with npiv support that is on the right fabric + + # Look via upstream interfaces + for fchost in /sys/class/fc_host/* ; do + if test -e $fchost/vport_create ; then + # is the link up, w/ NPIV support ? + pstate=`cat $fchost/port_state` + ptype=`cat $fchost/port_type | cut -c 1-5` + fname=`cat $fchost/fabric_name | sed -e s/^0x//` + if [ $pstate = "Online" -a $ptype = "NPort" -a $fname = $1 ] ; then + vmax=`cat $fchost/max_npiv_vports` + vinuse=`cat $fchost/npiv_vports_inuse` + avail=`expr $vmax - $vinuse` + if [ $avail -gt 0 ] ; then + # create the vport + echo $2":"$3 > $fchost/vport_create + if [ $? -eq 0 ] ; then + return 0 + fi + # failed - so we'll just look for the next adapter + fi + fi + fi + done + + # Look in vendor-specific locations + + # Emulex: interfaces mirror upstream, but are under adapter scsi_host + for shost in /sys/class/scsi_host/* ; do + if [ -e $shost/vport_create ] ; then + fchost=`ls -d $shost/device/fc_host*` + # is the link up, w/ NPIV support ? + pstate=`cat $fchost/port_state` + ptype=`cat $fchost/port_type | cut -c 1-5` + fname=`cat $fchost/fabric_name | sed -e s/^0x//` + if [ $pstate = "Online" -a $ptype = "NPort" -a $fname = $1 ] ; then + vmax=`cat $shost/max_npiv_vports` + vinuse=`cat $shost/npiv_vports_inuse` + avail=`expr $vmax - $vinuse` + if [ $avail -gt 0 ] ; then + # create the vport + echo $2":"$3 > $shost/vport_create + if [ $? -eq 0 ] ; then + return 0 + fi + # failed - so we'll just look for the next adapter + fi + fi + fi + done + + return 1 +} + + +# Look for the LUN on the indicated scsi_host (which is an NPIV vport) +# $1 is the scsi_host name (normalized to simply the hostX name) +# $2 is the WWPN of the tgt port the lun is on +# Note: this implies we don't support a multipath'd lun, or we +# are explicitly identifying a "path" +# $3 is the LUN number of the scsi device +find_sdev() +{ + unset dev + hostno=${1/*host/} + for sdev in /sys/class/scsi_device/${hostno}:*:$3 ; do + if test -e $sdev/device/../fc_trans*/target${hostno}*/port_name ; then + tgtwwpn=`cat $sdev/device/../fc_trans*/target${hostno}*/port_name | sed -e s/^0x//` + if test $tgtwwpn = $2 ; then + if test -e $sdev/device/block* ; then + dev=`ls $sdev/device/block*` + dev=${dev##*/} + return + fi + fi + fi + done +} + + +# Look for the NPIV vhost based on a scsi "sdX" name +# $1 is the "sdX" name +find_vhost_from_dev() +{ + unset vhost + hostno=`readlink /sys/block/$1/device` + hostno=${hostno##*/} + hostno=${hostno%%:*} + if test -z "$hostno" ; then return; fi + vhost="host"$hostno +} + + +# We're about to terminate a vhost based on a scsi device +# Flush all nodes on that vhost as they are about to go away +# $1 is the vhost +flush_nodes_on_vhost() +{ + if test ! -x /sbin/blockdev ; then return; fi + hostno=${1/*host/} + for sdev in /sys/class/scsi_device/${hostno}:* ; do + if test -e $sdev/device/block* ; then + dev=`ls $sdev/device/block*` + dev="/dev/"$dev + if test -n "$dev"; then + blockdev --flushbufs $dev + fi + fi + done +} + + +# Terminate a NPIV vhost +# $1 is vhost +delete_vhost() +{ + # use upstream interface + for vport in /sys/class/fc_vports/* ; do + if test -e $vport/device/$1 ; then + if test -e $vport/vport_delete ; then + echo "1" > $vport/vport_delete + if test $? -ne 0 ; then exit 6; fi + sleep 4 + return + fi + fi + done + + # use vendor specific interface + + # Emulex + if test -e /sys/class/fc_host/$1/device/../scsi_host*/lpfc_drvr_version ; then + shost=`ls -1d /sys/class/fc_host/$1/device/../scsi_host* | sed s/.*scsi_host://` + vportwwpn=`cat /sys/class/fc_host/$1/port_name | sed s/^0x//` + vportwwnn=`cat /sys/class/fc_host/$1/node_name | sed s/^0x//` + echo "$vportwwpn:$vportwwnn" > /sys/class/scsi_host/$shost/vport_delete + if test $? -ne 0 ; then exit 6; fi + sleep 4 + return + fi + + # Qlogic + if test -e /sys/class/fc_host/$1/device/../scsi_host*/driver_version ; then + shost=`ls -1d /sys/class/fc_host/$1/device/../scsi_host* | sed s/.*scsi_host://` + vportwwpn=`cat /sys/class/fc_host/$1/port_name | sed s/^0x//` + vportwwnn=`cat /sys/class/fc_host/$1/node_name | sed s/^0x//` + echo "$vportwwpn:$vportwwnn" > /sys/class/scsi_host/$shost/vport_delete + if test $? -ne 0 ; then exit 6; fi + sleep 4 + return + fi + + exit 6 +} + + +vport_status() +{ + # Look via upstream interfaces + for fchost in /sys/class/fc_host/* ; do + if test -e $fchost/vport_create ; then + vport_status_display $fchost $fchost + fi + done + + # Look in vendor-specific locations + + # Emulex: interfaces mirror upstream, but are under adapter scsi_host + for shost in /sys/class/scsi_host/* ; do + if [ -e $shost/vport_create ] ; then + fchost=`ls -d $shost/device/fc_host*` + vport_status_display $fchost $shost + fi + done + + return 0 +} + + +vport_status_display() +{ + echo + echo "fc_host: " $2 + echo "port_state: " `cat $1/port_state` + echo "port_type: " `cat $1/port_type` + echo "fabric_name: " `cat $1/fabric_name` + echo "max_npiv_vports: " `cat $2/max_npiv_vports` + echo "npiv_vports_inuse: " `cat $2/npiv_vports_inuse` + echo "modeldesc: " `cat $2/modeldesc` + echo "speed: " `cat $1/speed` + + return 0 +} + diff --git a/block-npiv-vport b/block-npiv-vport new file mode 100644 index 0000000..cab127b --- /dev/null +++ b/block-npiv-vport @@ -0,0 +1,79 @@ +#!/bin/bash + +# Usage: block-npiv-vport [create npivargs | delete vportwwpn | status] + +dir=$(dirname "$0") +. "$dir/block-npiv-common.sh" + +#set -x +command=$1 +params=$2 + +case "$command" in + create) + # Params is one big arg, with fields separated by hyphens: + # FABRIC-VPWWPN-VPWWNN-TGTWWPN-LUN# + # arg 2 - Fabric Name + # arg 3 - VPORT's WWPN + # arg 4 - VPORT's WWNN + # arg 5 - Target's WWPN + # arg 6 - LUN # on Target + # no wwn contains a leading 0x - it is a 16 character hex value + # You may want to optionally pick a specific adapter ? + NPIVARGS=$params; + LUN=${NPIVARGS##*-*-*-*-}; NPIVARGS=${NPIVARGS%-*} + if test $LUN = $NPIVARGS ; then exit 1; fi + TGTWWPN=${NPIVARGS##*-*-*-}; NPIVARGS=${NPIVARGS%-*} + if test $TGTWWPN = $NPIVARGS ; then exit 1; fi + VPORTWWNN=${NPIVARGS##*-*-}; NPIVARGS=${NPIVARGS%-*} + if test $VPORTWWNN = $NPIVARGS ; then exit 1; fi + VPORTWWPN=${NPIVARGS##*-}; NPIVARGS=${NPIVARGS%-*} + if test $VPORTWWPN = $NPIVARGS ; then exit 1; fi + FABRICNM=$NPIVARGS + + # Ensure we compare everything using lower-case hex characters + TGTWWPN=`echo $TGTWWPN | tr A-Z a-z` + VPORTWWPN=`echo $VPORTWWPN | tr A-Z a-z` + VPORTWWNN=`echo $VPORTWWNN | tr A-Z a-z` + FABRICNM=`echo $FABRICNM | tr A-Z a-z` + + find_vhost $VPORTWWPN + if test -z "$vhost" ; then + create_vport $FABRICNM $VPORTWWPN $VPORTWWNN + if [ $? -ne 0 ] ; then exit 2; fi + sleep 8 + find_vhost $VPORTWWPN + if test -z "$vhost" ; then exit 3; fi + fi + + exit 0 + ;; + + delete) + # Params is VPORT's WWPN + # no wwn contains a leading 0x - it is a 16 character hex value + VPORTWWPN=$params + + # Ensure we compare everything using lower-case hex characters + VPORTWWPN=`echo $VPORTWWPN | tr A-Z a-z` + + find_vhost $VPORTWWPN + if test -z "$vhost" ; then exit 4; fi + delete_vhost $vhost + + exit 0 + ;; + + status) + vport_status + + exit 0 + ;; + + *) + echo "Usage: block-npiv-vport [create npivargs | delete vportwwpn | status]" + + exit 1 + ;; +esac + diff --git a/xen-qemu-iscsi-fix.patch b/xen-qemu-iscsi-fix.patch index 2a0e983..5bf0307 100644 --- a/xen-qemu-iscsi-fix.patch +++ b/xen-qemu-iscsi-fix.patch @@ -31,12 +31,12 @@ Index: xen-3.4.1-testing/tools/ioemu-remote/xenstore.c continue; + + free(params); -+ if (!strcmp(drv,"iscsi")) ++ if (!strcmp(drv,"iscsi") || !strcmp(drv, "npiv")) + { + if (pasprintf(&buf, "%s/node", bpath) == -1) + continue; + -+ /* wait for block-iscsi script to complete and populate the ++ /* wait for block-[iscsi|npiv] script to complete and populate the + * node entry. try 30 times (30 secs) */ + for (j = 0; j < 30; j++) { + params = xs_read(xsh, XBT_NULL, buf, &len); @@ -45,7 +45,7 @@ Index: xen-3.4.1-testing/tools/ioemu-remote/xenstore.c + sleep(1); + } + if (params == NULL) { -+ fprintf(stderr, "qemu: iscsi device not found -- timed out \n"); ++ fprintf(stderr, "qemu: %s device not found -- timed out \n", drv); + continue; + } + } diff --git a/xen.changes b/xen.changes index a3a5c03..2594ec3 100644 --- a/xen.changes +++ b/xen.changes @@ -5,6 +5,14 @@ Fri Sep 25 15:08:12 MDT 2009 - jfehlig@novell.com qemu-dm reading from xenstore. The issue is preventing PV domUs from booting as they have no backend console. qemu-retry-be-status.patch +- bnc#520234 - npiv does not work with XEN + Update block-npiv +- bnc#496033 - Support for creating NPIV ports without starting vm + block-npiv-common.sh + block-npiv-vport + Update block-npiv +- bnc#500043 - Fix access to NPIV disk from HVM vm + Update xen-qemu-iscsi-fix.patch ------------------------------------------------------------------- Tue Sep 15 09:32:59 MDT 2009 - jfehlig@novell.com diff --git a/xen.spec b/xen.spec index dcd70ed..c3419b2 100644 --- a/xen.spec +++ b/xen.spec @@ -56,7 +56,9 @@ Source9: xmexample.domUloader Source10: xmexample.disks Source11: block-nbd Source12: block-iscsi -Source13: block-npiv +Source13: block-npiv-common.sh +Source14: block-npiv +Source15: block-npiv-vport Source16: xmclone.sh Source17: xend-relocation.sh Source18: init.xen_loop @@ -735,7 +737,7 @@ rm -f $RPM_BUILD_ROOT/etc/xen/examples/*nbd install -m644 %SOURCE9 %SOURCE10 $RPM_BUILD_ROOT/etc/xen/examples/ # scripts rm -f $RPM_BUILD_ROOT/etc/xen/scripts/block-*nbd -install -m755 %SOURCE11 %SOURCE12 %SOURCE13 %SOURCE16 %SOURCE17 $RPM_BUILD_ROOT/etc/xen/scripts/ +install -m755 %SOURCE11 %SOURCE12 %SOURCE13 %SOURCE14 %SOURCE15 %SOURCE16 %SOURCE17 $RPM_BUILD_ROOT/etc/xen/scripts/ ln -s /etc/xen/scripts/vm-monitor $RPM_BUILD_ROOT/etc/xen/scripts/set-lock # Xen API remote authentication files install -d $RPM_BUILD_ROOT/etc/pam.d