#!/bin/bash
# OCF Resource Agent for NVMe-oF initiator

: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs

NQN="${OCF_RESKEY_nqn}"
ADDR="${OCF_RESKEY_addr}"
PORT="${OCF_RESKEY_port:-4420}"
TRANSPORT="${OCF_RESKEY_transport:-tcp}"

nvme_paths() {
    for addr in ${ADDR}; do
        printf '%s\n' "${addr}"
    done
}

nvme_status() {
    nvme list-subsys 2>/dev/null | grep -q "${NQN}"
}

nvme_path_count() {
    nvme list-subsys 2>/dev/null | awk -v nqn="${NQN}" '
        $0 ~ "NQN=" nqn { in_subsys=1; next }
        in_subsys && $0 ~ /^nvme-subsys/ { exit }
        in_subsys && $0 ~ /[[:space:]]nvme[0-9]+[[:space:]]/ { count++ }
        END { print count + 0 }
    '
}

nvme_start() {
    local addr

    for addr in $(nvme_paths); do
        nvme connect -t "${TRANSPORT}" -a "${addr}" -s "${PORT}" -n "${NQN}" || true &
    done

    wait
    sleep 2

    nvme_status && return $OCF_SUCCESS
    return $OCF_ERR_GENERIC
}

nvme_stop() {
    nvme_status || return $OCF_SUCCESS
    nvme disconnect -n "${NQN}"
    nvme_status && return $OCF_ERR_GENERIC
    return $OCF_SUCCESS
}

nvme_monitor() {
    nvme_status || return $OCF_NOT_RUNNING

    if [ "$(nvme_path_count)" -gt 0 ]; then
        return $OCF_SUCCESS
    fi

    return $OCF_NOT_RUNNING
}

case "$1" in
    start)   nvme_start ;;
    stop)    nvme_stop ;;
    monitor) nvme_monitor ;;
    meta-data)
        cat << 'META'
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="nvme-initiator">
<version>1.0</version>
<parameters>
<parameter name="nqn" required="1"><longdesc>NVMe NQN</longdesc><shortdesc>NQN</shortdesc><content type="string"/></parameter>
<parameter name="addr" required="1"><longdesc>Target address. For multipath, pass a space-separated list of target IPs.</longdesc><shortdesc>addr</shortdesc><content type="string"/></parameter>
<parameter name="port"><longdesc>Target port</longdesc><shortdesc>port</shortdesc><content type="string" default="4420"/></parameter>
<parameter name="transport"><longdesc>Transport type</longdesc><shortdesc>transport</shortdesc><content type="string" default="tcp"/></parameter>
</parameters>
<actions>
<action name="start" timeout="30s"/>
<action name="stop" timeout="30s"/>
<action name="monitor" interval="10s" timeout="20s"/>
</actions>
</resource-agent>
META
        ;;
    validate-all) exit $OCF_SUCCESS ;;
    *) exit $OCF_ERR_UNIMPLEMENTED ;;
esac
