#!/usr/bin/bash
#
# Copyright (c) 2006, 2025, Oracle and/or its affiliates.
#
# Configure the oracleasm startup scripts.
#

# Force LC_ALL=C
export LC_ALL=C
 
USAGE="[-i|-I] [-e|-d] [-u <user>] [-g <group>] [-b|-p] [-s y|n] [-f y|n] [-m <max-disks>] [[-o <order>] ...] [[-x <exclude>] [-D <scan_directories>...]"

exec 3>/dev/null

if [ $# = 0 ]
then
    list=t
else
    list=
fi
help=
verbose=
version=
usage=
interactive=
dirlist=
backslash="/"
oracleasm_uid=
oracleasm_gid=
oracleasm_scanboot=
oracleasm_scanorder=
oracleasm_scanexclude=
oracleasm_scan_directories=
oracleasm_use_logical_block_size=
oracleasm_config_max_disks=2048
oracleasm_enable_iofilter=true
while case "$#" in 0) break ;; esac
do
    case "$1" in
    -i|--interactive)
        interactive=t
        ;;
    -I|--interactive-all)
        interactive=T  # Ask advanced questions
        ;;
    -e|--enable)
        systemctl enable oracleasm.service
        ;;
    -d|--disable)
        systemctl disable oracleasm.service
        ;;
    -u|--uid|--user)
        case "$#" in 1) usage=t; break ;; esac
        shift
        oracleasm_uid="$1"
        ;;
    -g|--gid|--group)
        case "$#" in 1) usage=t; break ;; esac
        shift
        oracleasm_gid="$1"
        ;;
    -s|--scanboot)
        case "$#" in 1) usage=t; break ;; esac
        shift
        case "$1" in
        [tT]|[tT][rR][uU][eE]|[yY]|[yY][eE][sS])
            oracleasm_scanboot=true
            ;;
        [fF]|[fF][aA][lL][sS][eE]|[nN]|[nN][oO])
            oracleasm_scanboot=false
            ;;
        *) usage=t; break ;;
        esac
        ;;
    -o|--scanorder)
        case "$#" in 1) usage=t; break ;; esac
        shift
        if [ "$oracleasm_scanorder" = "none" ]
        then
            oracleasm_scanorder=
        fi

        case "$1" in
        ""|none)
            oracleasm_scanorder=none
            ;;
        *[^a-zA-Z0-9\ ]*)
            usage=t; break
            ;;
        *)
            oracleasm_scanorder="${oracleasm_scanorder:+$oracleasm_scanorder }$1"
            ;;
        esac
        ;;
    -x|--scanexclude)
        case "$#" in 1) usage=t; break ;; esac
        shift
        if [ "$oracleasm_scanexclude" = "none" ]
        then
            oracleasm_scanexclude=
        fi

        case "$1" in
        ""|none)
            oracleasm_scanexclude=none
            ;;
        *[^a-zA-Z0-9/\ ]*)
            usage=t; break
            ;;
        *)
            oracleasm_scanexclude="${oracleasm_scanexclude:+$oracleasm_scanexclude }$1"
            ;;
        esac
        ;;
    -D|--scan_directories)
        case "$#" in 1) usage=t; break ;; esac
        shift
        if [ "$oracleasm_scan_directories" = "none" ]
        then
            oracleasm_scan_directories=
        fi

        case "$1" in
        ""|none)
            oracleasm_scan_directories=none
            ;;
        *[^a-zA-Z0-9/\ ]*)
            usage=t; break
            ;;
        *)
            oracleasm_scan_directories="${oracleasm_scan_directories:+$oracleasm_scan_directories }$1"
            ;;
        esac
        ;;
    -b|--logical-blocks)
	oracleasm_use_logical_block_size=true
	;;
    -p|--physical-blocks)
	oracleasm_use_logical_block_size=false
	;;
    -v|--verbose)
        verbose=t
        exec 3>&2
        ;;
    -V|--version)
        version=t
        ;;
    -h|--help)
        help=t
        ;;
    -m|--maxdev)
        case "$#" in 1) usage=t; break ;; esac
        shift
        oracleasm_config_max_disks="$1"
        ;;
    -f|--iofilter)
        case "$#" in 1) usage=t; break ;; esac
        shift
        case "$1" in
        [tT]|[tT][rR][uU][eE]|[yY]|[yY][eE][sS])
            oracleasm_enable_iofilter=true
            ;;
        [fF]|[fF][aA][lL][sS][eE]|[nN]|[nN][oO])
            oracleasm_enable_iofilter=false
            ;;
        *) usage=t; break ;;
        esac
        ;;
    *)
        usage=t
        ;;
    esac
    shift
done

# Load configuration
. oracleasm-Xshlib

if [ "$help" = "t" -o "$usage" = "t" ]
then
    usage
fi

if [ "$version" = "t" ]
then
    version
fi

if [ "$list" = "t" ]
then
    cat <<EOF
ORACLEASM_UID=${ORACLEASM_UID}
ORACLEASM_GID=${ORACLEASM_GID}
ORACLEASM_SCANBOOT=${ORACLEASM_SCANBOOT:-false}
ORACLEASM_SCANORDER="${ORACLEASM_SCANORDER}"
ORACLEASM_SCANEXCLUDE="${ORACLEASM_SCANEXCLUDE}"
ORACLEASM_SCAN_DIRECTORIES="${ORACLEASM_SCAN_DIRECTORIES}"
ORACLEASM_USE_LOGICAL_BLOCK_SIZE="${ORACLEASM_USE_LOGICAL_BLOCK_SIZE:-false}"
ORACLEASM_CONFIG_MAX_DISKS="${ORACLEASM_CONFIG_MAX_DISKS:-2048}"
ORACLEASM_ENABLE_IOFILTER="${ORACLEASM_ENABLE_IOFILTER:-true}"
EOF
    exit 0
fi

[ -n "$oracleasm_uid" ] && ORACLEASM_UID="$oracleasm_uid"
[ -n "$oracleasm_gid" ] && ORACLEASM_GID="$oracleasm_gid"
[ -n "$oracleasm_scanboot" ] && ORACLEASM_SCANBOOT="$oracleasm_scanboot"
[ -n "$oracleasm_use_logical_block_size" ] && ORACLEASM_USE_LOGICAL_BLOCK_SIZE="$oracleasm_use_logical_block_size"
[ -n "$oracleasm_config_max_disks" ] && ORACLEASM_CONFIG_MAX_DISKS="$oracleasm_config_max_disks"
[ -n "$oracleasm_enable_iofilter" ] && ORACLEASM_ENABLE_IOFILTER="$oracleasm_enable_iofilter"

if [ -n "$oracleasm_scanorder" ]
then
    [ "$oracleasm_scanorder" = "none" ] && oracleasm_scanorder=
    ORACLEASM_SCANORDER="$oracleasm_scanorder"
fi

if [ -n "$oracleasm_scanexclude" ]
then
    [ "$oracleasm_scanexclude" = "none" ] && oracleasm_scanexclude=
    ORACLEASM_SCANEXCLUDE="$oracleasm_scanexclude"
fi

if [ -n "$oracleasm_scan_directories" ]
then
    [ "$oracleasm_scan_directories" = "none" ] && oracleasm_scan_directories=
    ORACLEASM_SCAN_DIRECTORIES="$oracleasm_scan_directories"
fi


#
# write_sysconfig()
#
# Writes the system configuration out
#
write_sysconfig()
{
    echo -n "Writing Oracle ASM system service configuration: "
    cat >"${ORACLEASM_CONFIG}" 2>&3 <<EOF
#
# This is the configuration file for the Oracle Automatic Storage
# Management system service. This file is generated by running
# 'oracleasm configure'. Please use that method to modify this file.
#

# ORACLEASM_UID: Default user owning ASM disk devices.
ORACLEASM_UID=${ORACLEASM_UID}

# ORACLEASM_GID: Default group owning ASM disk devices.
ORACLEASM_GID=${ORACLEASM_GID}

# ORACLEASM_SCANBOOT: 'true' means scan for ASM disks when the service
# starts.
ORACLEASM_SCANBOOT=${ORACLEASM_SCANBOOT}

# ORACLEASM_SCANORDER: Matching patterns to order disk scanning.
ORACLEASM_SCANORDER="${ORACLEASM_SCANORDER}"

# ORACLEASM_SCANEXCLUDE: Matching patterns to exclude disks from scan.
ORACLEASM_SCANEXCLUDE="${ORACLEASM_SCANEXCLUDE}"

# ORACLEASM_SCAN_DIRECTORIES: Scan disks under these directories
ORACLEASM_SCAN_DIRECTORIES="${ORACLEASM_SCAN_DIRECTORIES}"

# ORACLEASM_USE_LOGICAL_BLOCK_SIZE: 'true' means use the logical block
# size reported by the underlying disk instead of the physical. The
# default is 'false'.
ORACLEASM_USE_LOGICAL_BLOCK_SIZE=${ORACLEASM_USE_LOGICAL_BLOCK_SIZE}

# ORACLEASM_CONFIG_MAX_DISKS: Maximum number of ASM disks that may be
# used in the system. The default is 2048.
ORACLEASM_CONFIG_MAX_DISKS=${ORACLEASM_CONFIG_MAX_DISKS}

# ORACLEASM_ENABLE_IOFILTER: 'true' means to setup iofilter for ASM
# disks if the kernel supports BPF.
ORACLEASM_ENABLE_IOFILTER=${ORACLEASM_ENABLE_IOFILTER:-true}

EOF

    if [ $? != 0 ]
    then
        die "Unable to write Oracle ASM system service configuration"
    fi

    echo "done"

    cat <<EOF

Configuration changes only come into effect after the Oracle ASM
system service is restarted.  Please run 'systemctl restart oracleasm'
after making changes.

WARNING: All of your Oracle and ASM instances must be stopped prior
to restarting the oracleasm service.

EOF
    return
}


#
# configure_ask()
#
# Ask configuration questions, setting the shell vars.
#
configure_ask()
{
    cat <<EOF
Configuring the Oracle ASM system service.

This will configure the on-boot properties of the Oracle ASM system
service.  The following questions will determine whether the service
is started on boot and what permissions it will have.  The current
values will be shown in brackets ('[]').  Hitting <ENTER> without
typing an answer will keep that current value.  Ctrl-C will abort.

EOF

    while :
    do
        echo -n "Default user to own the ASM disk devices [$ORACLEASM_UID]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        *[^a-zA-Z0-9]*)
            echo "Invalid user: $LINE" >&2
            ;;
        *)
            ORACLEASM_UID=$LINE
            break
            ;;
        esac
    done

    while :
    do
        echo -n "Default group to own the ASM disk devices [$ORACLEASM_GID]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        *[^a-zA-Z0-9]*)
            echo "Invalid group: $LINE" >&2
            ;;
        *)
            ORACLEASM_GID=$LINE
            break
            ;;
        esac
    done

    while :
    do
	if [ `systemctl is-enabled oracleasm.service` == "enabled" ]
	then
	    CUR=y
        else
            CUR=n
        fi
        echo -n "Start Oracle ASM system service on boot (y/n) [$CUR]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        y|Y)
            systemctl enable oracleasm.service
            break
            ;;
        n|N)
            systemctl disable oracleasm.service
            break
            ;;
        *)
            echo "Invalid response: $LINE" >&2
            ;;
        esac
    done

    while :
    do
        if [ -z "$ORACLEASM_SCANBOOT" ]
        then
            ORACLEASM_SCANBOOT=true
        fi
        if [ "${ORACLEASM_SCANBOOT}" = "true" ]
        then
            CUR=y
        else
            CUR=n
        fi
        echo -n "Scan for Oracle ASM disks when starting the oracleasm service (y/n) [$CUR]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        y|Y)
            ORACLEASM_SCANBOOT=true
            break
            ;;
        n|N)
            ORACLEASM_SCANBOOT=false
            break
            ;;
        *)
            echo "Invalid response: $LINE" >&2
            ;;
        esac
    done

    while :
    do
        echo -n "Maximum number of ASM disks that can be used on system [$ORACLEASM_CONFIG_MAX_DISKS]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        *[^0-9]*)
            echo "Invalid value: $LINE" >&2
            ;;
        *)
            ORACLEASM_CONFIG_MAX_DISKS=$(expr $LINE)
            break
            ;;
        esac
    done

    while :
    do
        if [ "$ORACLEASM_ENABLE_IOFILTER" = "true" ]
        then
            CUR=y
        else
            CUR=n
        fi
        echo -n "Enable iofilter if kernel supports it (y/n) [$CUR]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        y|Y)
            ORACLEASM_ENABLE_IOFILTER=true
            break
            ;;
        n|N)
            ORACLEASM_ENABLE_IOFILTER=false
            break
            ;;
        *)
            echo "Invalid response: $LINE" >&2
            ;;
        esac
    done
}

configure_ask_advanced()
{
    cat <<EOF

The next two configuration options take substrings to match device names.
The substring "sd" (without the quotes), for example, matches "sda", "sdb",
etc.  You may enter more than one substring pattern, separated by spaces.
The special string "none" (again, without the quotes) will clear the value.

EOF

    while :
    do
        echo -n "Device order to scan for ASM disks [$ORACLEASM_SCANORDER]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        none)
            ORACLEASM_SCANORDER=
            ;;
        *[^a-zA-Z0-9\ ]*)
            echo "Invalid pattern: $LINE" >&2
            ;;
        *)
            ORACLEASM_SCANORDER="$LINE"
            break
            ;;
        esac
    done

    while :
    do
        echo -n "Devices to exclude from scanning [$ORACLEASM_SCANEXCLUDE]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        none)
            ORACLEASM_SCANEXCLUDE=
            ;;
        *[^a-zA-Z0-9\ ]*)
            echo "Invalid pattern: $LINE" >&2
            ;;
        *)
            ORACLEASM_SCANEXCLUDE="$LINE"
            break
            ;;
        esac
    done

    while :
    do
        echo -n "Directories to scan [$ORACLEASM_SCAN_DIRECTORIES]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        none)
            ORACLEASM_SCAN_DIRECTORIES=
            ;;
        *[^a-zA-Z0-9/\ ]*)
            echo "Invalid pattern: $LINE" >&2
            ;;
        *)
            for dir in $LINE
            do
                case $dir in
		*/)
		    dirlist="$dirlist $dir"
		    ;;
		 *)
		    dirlist="$dirlist $dir$backslash"
		    ;;
		esac
	    done
	    ORACLEASM_SCAN_DIRECTORIES=$dirlist
            break
            ;;
        esac
    done

    while :
    do
        if [ "$ORACLEASM_USE_LOGICAL_BLOCK_SIZE" = "true" ]
        then
            CUR=y
        else
            CUR=n
        fi
        echo -n "Use device logical block size for ASM (y/n) [$CUR]: "
        read LINE
        case "$LINE" in
        "")
            break
            ;;
        y|Y)
            ORACLEASM_USE_LOGICAL_BLOCK_SIZE=true
            break
            ;;
        n|N)
            ORACLEASM_USE_LOGICAL_BLOCK_SIZE=false
            break
            ;;
        *)
            echo "Invalid response: $LINE" >&2
            ;;
        esac
    done

}



[ -n "$interactive" ] && configure_ask
[ "$interactive" = "T" ] && configure_ask_advanced

check_iofilter
write_sysconfig

exit 0
