免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1615 | 回复: 0
打印 上一主题 下一主题

VXVM-------mirrors the root disk cleanly and safely [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-08-30 18:03 |只看该作者 |倒序浏览
#! /bin/sh
#
# mirrorRoot - mirrors the root disk cleanly and safely
#
################################################################
# Author: Todd Stansell <todd@stansell.org>;
# $Id: mirrorRoot,v 1.21 2004-02-01 03:40:20-08 todd Exp $
#
# Notes:
#
#   1) I use vxprint -F ... throughout this script because of the
#      fact that vxprint -ht output is not consistent between versions.
#      Version 3.1 adds information about replication (since it's
#      now integrated).  Anyway, by pulling only the information
#      I need, I can be sure it will work without regard to version.
#
#   2) status codes of all veritas commands are documented in the
#      vxintro manpage.
#
#   3) versions previous to 1.18 don't deal with the Block0
#      subdisk correctly for VxVM 3.5.  So, make sure you're
#      using version 1.18 or newer.  You wouldn't see this
#      message if you weren't, though.
#
################################################################
mirror_dev="c0t1d0"
mirror_name="rootdisk2"
verbose=0
c_opt=false
setswaponly=false
PATH=$PATH:/usr/sbin:/etc/vx/bin
PROG=`basename $0`
USAGE="usage: $PROG [-hvc] [ [-s] | [-n name] [-d device] ]
        -h   help
        -s   create swap slices and configure dump device only
        -v   increase verbosity level (two -v's for max)
        -c   show vx commands as they are run
   -n name   disk access name of mirror disk (default is $mirror_name)
-d device   device used to mirror onto (default is $mirror_dev)"

#
# kills off any processes that are running in the background
#
cleanup() {
    vxtask abort $PROG
}

#
# echo a message if we want vx command verbosity
#
show() { [ $c_opt ] && /bin/echo "# $@" ; }

#
# echo a message if we want verbosity
#
msg() { [ $verbose -ge 1 ] && /bin/echo "$@" ; }

#
# usage: showstatus $value $prog $msg
#
showstatus() {
    status="$1"
    prog="$2"
    if [ $status -ne 0 ] ; then
        echo "$3" >;&2
        echo "  $prog exited with status $status" >;&2
        exit $status
    fi
}

#
# Check to see that $device has at least $size sectors
# usage: check_size $device $size
#
check_size() {
    len=`vxprint -e 'sd && sd_disk="'$dm_of_rootvol'" && p0 = "RIVATE"' -F "%len" | awk '{a=a+$1}END{print '$2'-a}'`
    pub_len=`vxdisk list $1 | awk -F= '/^public:/ {print $NF}'`
    if [ $pub_len -lt $len ] ; then
        echo "$mirror_dev is only $pub_len sectors, while" >;&2
        echo "$dm_of_rootvol uses $len sectors.  Please choose a larger disk." >;&2
        exit 7
    fi
}

#
# usage: initdisk $device
#
initdisk() {
    dev=$1

    # see if we need the old_layout option to vxdisksetup.  This
    # is required if we have a fully-utilized disk that has been
    # encapsulated, so that only 1 cylinder is used for the private
    # region, and the new disk will have enough public space to
    # mirror everything to.  If you don't want it to use this option,
    # then initialize the disk before running this script.
    opt=""
    if grep old_layout /etc/vx/bin/vxdisksetup >;/dev/null ; then
        opt="old_layout"
    fi

    msg "Initializing $dev for use with volume manager"
    show "vxdisksetup -i $dev $opt"
    vxdisksetup -i $dev $opt; status=$?
    showstatus $status vxdisksetup "Could not initialize $dev"
}

#
# adds a device ($dev) to a disk group ($dg) with specified media name ($dm)
#
# usage: add_to_dg $dev $dm [$dg]
#
add_to_dg() {
    dg=rootdg
    dev=$1
    dm=$2
    [ "$3" ] && dg=$3
    msg "Adding $dev to $dg as $dm"
    show "vxdg -g $dg adddisk $dm=$dev"
    vxdg -g $dg adddisk $dm=$dev; status=$?
    showstatus $status vxdg "Could not add $dev to $dg as \"$dm\""
}

#
# Display the running tasks with the current date
#
# usage: showtasks
#
showtasks() {
    echo ============= `date` =============
    vxtask -l list $PROG | egrep "Operation|Work|Progress|^$"
}

#
# simply waits for all tasks with our taskid ($PROG) have finished
#
# usage: taskwait
#
taskwait() {
    out=`vxtask list $PROG 2>;&1`
    status=$?
    i=0; o=`echo "$out" | wc -l`
    [ $status -eq 0 -a $verbose -ge 2 ] && showtasks
    while [ $status -eq 0 ] ; do
        if [ $verbose -ge 2 ] ; then
            u=`echo "$out" | wc -l`
            if [ $u -ne $o ] ; then
                showtasks
                o=$u
            fi
            j=`expr $i % 4`
            case $j in
                0)        /bin/echo '|\r\c' ;;
                1)        /bin/echo '/\r\c' ;;
                2)        /bin/echo '-\r\c' ;;
                3)        /bin/echo '\\\r\c' ;;
            esac
            i=`expr $i + 1`
        fi
        sleep 2
        out=`vxtask list $PROG 2>;&1`
        status=$?
    done
}

#
# usage: mirrorto $dmname
#
mirrorto() {
    dm=$1

    #
    # We start by mirroring rootvol, since it's special
    #
    msg "Starting mirror of rootvol to $dm..."
    show "vxrootmir -t $PROG $dm"
    vxrootmir -t $PROG $dm ; status=$?
    showstatus $status vxrootmir "Could not mirror rootvol to $dm"

    #
    # Now mirror the rest of the volumes.
    #
    for vol in $vols_on_dm ; do
        if [ $vol = "rootvol" ] ; then
                continue
        fi
        msg "Starting mirror of $vol onto $dm..."
        show "vxassist -b -g rootdg -t $PROG mirror $vol $dm"
        vxassist -b -g rootdg -t $PROG mirror $vol $dm; status=$?
        showstatus $status vxassist "Mirror of $vol onto $dm FAILED"
    done

    taskwait
}

#
# make sure swap has a valid partition entry so
# we can use it as a dump device, and also set
# dumpadm to use that new slice.
#
setSwap() {
    swap=`vxprint -g rootdg -e 'sd && assoc.assoc.v_use_type="swap"' -F '%name'`
    if [ -n "swap" ] ; then
            msg "Making sure $swap has valid partition entries."
            slice=""
            for sd in $swap ; do
                    # vxmksdpart -g rootdg <subdisk>; <partition #>; <tag>; <flags>;
                    show "vxmksdpart -g rootdg $sd 1 0x03 0x01"
                    if [ -z "$slice" ] ; then
                        slice="`vxprint -g rootdg -F '%device_tag' $sd`s1"
                    fi
            done

            if [ -f /etc/dumpadm.conf ] ; then
                if [ -n "$slice" ] ; then
                    msg "Configuring dumpadm for swap slice $slice"
                    show "dumpadm -d /dev/dsk/$slice"
                else
                    echo "Could not determine slice to use for dump device!" >;&2
                fi
            fi
    fi
}

#############################################
#         BEGIN MAIN PROGRAM
#############################################

#
# lets try to clean things up if we die
#
trap cleanup 1 2 3 5 15

while getopts vcsn:d:h c; do
        case $c in
        v)        verbose=`expr $verbose + 1`
                ;;
        c)        c_opt="true"
                ;;
        n)        mirror_name=$OPTARG
                ;;
        d)        mirror_dev=$OPTARG
                ;;
        s)        setswaponly=true
                ;;
        *)        echo "$USAGE" >;&2
                exit 64
                ;;
        esac
done
shift `expr $OPTIND - 1`

#########
# Make sure a bunch of stuff is ok before we begin
#########

# make sure we're root
if /bin/id | grep -v '^uid=0(' >;/dev/null ; then
        echo "$PROG: must be run as root" >;&2
        exit 64
fi

# make sure vxvm is installed
if pkginfo VRTSvxvm >;/dev/null 2>;&1 ; then
        version=`pkginfo -x VRTSvxvm | tail -1 | sed 's/.*) \(.\).*/\1/'`
else
        echo "$PROG: VRTSvxvm not installed" >;&2
        exit 64
fi

# make sure vxvm is 3.x or greater
if [ -z "$version" -o $version -lt 3 ] ; then
        echo "$PROG: This script requires VRTSvxvm 3.x or greater to function." >;&2
        exit 64
fi

# make sure we're encapsulated
vxprint -g rootdg rootvol >;/dev/null
if [ $? -ne 0 ] ; then
        echo "$PROG: rootvol doesn't exist.  This probably means" >;&2
        echo "your root disk is not encapsulated yet." >;&2
        exit 64
fi

if $setswaponly ; then
        setSwap
        exit
fi

#########
# Now we should be ready to go...
#########

#
# Find out where we're mirroring from, and what that includes.
#
dm_of_rootvol=`vxprint -r -g rootdg -F "%rtype %name" rootvol | \
                awk '/^dm/{print $NF; exit}'`
dev_of_rootvol=`vxprint -g rootdg -F "%device_tag" $dm_of_rootvol`
msg "using $dm_of_rootvol to determine volumes to mirror..."

sds_on_dm=`vxprint -g rootdg \
                -e 'sd_disk = "'$dm_of_rootvol'"' \
                -F "%name" | sort`
plexs_on_dm=`vxprint -g rootdg \
                -e 'pl_subdisk.sd_disk = "'$dm_of_rootvol'"' \
                -F "%name" | sort`
vols_on_dm=`vxprint -g rootdg \
                -e 'v_plex.pl_subdisk.sd_disk = "'$dm_of_rootvol'"' \
                -F "%name" | sort`

msg "  volumes to be mirrored: "$vols_on_dm

size_of_dm=`vxprint -F "%len" $sds_on_dm | awk '{a=a+$1}END{print a}'`
msg "  total space required: $size_of_dm sectors"

#
# Check if $mirror_dev is being used already.
#
msg "Checking \"$mirror_dev\" for use as destination mirror..."
for dg in `vxdg -q list | grep -v rootdg | awk '{print $1}'` ; do
        dev=`vxprint -d -g $dg -F "%name %device_tag" | \
                awk '$NF=="'$mirror_dev'" {print $1}'`
        if [ ! -z "$dev" ] ; then
                echo "$mirror_dev is used in the $dg disk group as $dev" >;&2
                exit 5
        fi
done

#
# We check to see if $mirror_dev is part of rootdg
#
dm_mirror=`vxprint -d -g rootdg -F "%name %device_tag" | \
        awk '$NF=="'$mirror_dev'" {print $1}'`
if [ -n "$dm_mirror" ] ; then
        #
        # $mirror_dev is already part of rootdg, now see if it's being used
        #
        sd_num=`vxprint -F "%sd_num" $dm_mirror`
        if [ $sd_num -gt 0 ] ; then
            echo "$dm_mirror ($mirror_dev) already belongs to rootdg and" >;&2
            echo "contains $sd_num subdisks.  Please choose a different" >;&2
            echo "device to use or clean out $mirror_dev" >;&2
            exit 6
        fi
        #
        # verify space requirements
        #
        check_size $mirror_dev $size_of_dm
else
        #
        # the device ($mirror_dev) is not part of a disk group.  Now we
        # check if it is currently initialized.  If not, we initialize it.
        # Then, we make sure it's part of rootdg.
        #
        dm_mirror=$mirror_name
        show "vxdisk list $mirror_dev"
        vxdisk list $mirror_dev | grep "^private:" >;/dev/null; status=$?
        if [ $status -eq 0 ] ; then
                #
                # the disk is initialized already
                #
                msg "$mirror_dev is already initialized and unallocated."
        else
                initdisk $mirror_dev
        fi

        #
        # verify device is large enough
        #
        check_size $mirror_dev $size_of_dm

        #
        # now add the disk to rootdg
        #
        add_to_dg $mirror_dev $dm_mirror rootdg
fi

#
# At this point, we have an initialized, clean disk in rootdg
# named $dm_mirror that is large enough to hold all of the volumes.
#
mirrorto $dm_mirror

#
# Now we need to check if the original disk was an encapsulated
# one, or if it was already converted to an initialized one.
#

priv=`vxprint -e 'sd && \
                  sd_disk="'$dm_of_rootvol'" && \
                  putil0!=""' \
              -F "%name"`
# $priv should now be something like "rootdiskPriv" or "rootdisk1Priv"
if [ -n "$priv" ] && echo $sds_on_dm | grep "$priv" >;/dev/null ; then
        msg "$dm_of_rootvol appears to be encapsulated, continuing..."
else
        msg "$dm_of_rootvol does not appear to be encapsulated.  We're done."
        exit 0
fi

msg "Removing all mirrors that use $dm_of_rootvol..."
for vol in $vols_on_dm ; do
        msg "  removing from $vol...\c"
        show "vxassist -g rootdg remove mirror $vol \!$dm_of_rootvol"
        vxassist -g rootdg remove mirror $vol \!$dm_of_rootvol; status=$?
        if [ $status -ne 0 ] ; then
                msg "FAILED"
        fi
        showstatus $status vxassist "Failed to remove mirror of $vol"
        msg "ok"
done

#
# remove the encapsulation private subdisk (typically, rootdiskPriv)
#
if [ -z "$priv" ] ; then
        echo "No private subdisk found?  This isn't normally the case."
else
        if vxprint -e 'sd && sd_name="'%priv'"' >;/dev/null ; then
                show "vxedit -g rootdg rm $priv"
                vxedit -g rootdg rm $priv
                status=$?
                showstatus $status vxedit "Failed to remove $priv subdisk from rootdg"
        fi
fi

#
# remove disk from rootdg
#
msg "Removing $dm_of_rootvol from rootdg..."
show "vxdg -g rootdg rmdisk $dm_of_rootvol"
vxdg -g rootdg rmdisk $dm_of_rootvol; status=$?
showstatus $status vxdg "Failed to remove $dm_of_rootvol from rootdg"

#
# re-initialize the disk
#
initdisk $dev_of_rootvol

#
# add the disk to rootdg
#
add_to_dg $dev_of_rootvol $dm_of_rootvol rootdg

#
# mirroring volumes.
#
mirrorto $dm_of_rootvol

setSwap
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP