#!/bin/bash

# Copyright: 2023 Virtuozzo International GmbH

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

inherit os output tests;
include log virtuozzo vzexec;

DESCRIPTION="Manipulate storage mounts inside specified container";
VERSION="1"
DEFAULT_ACTION="Usage";

$PROGRAM "vzctl"
$PROGRAM "prlctl"
$PROGRAM "vzlist"
$PROGRAM "awk"
$PROGRAM "ifconfig"
$PROGRAM "rsync"
$PROGRAM "grep"
$PROGRAM "tar"

declare -i _CTID=""
declare -i CTID=""
declare VEID=""
declare -i _MOVEDATA=0
declare CLUSTER="false"
declare _SOURCE=""
declare _DESTINATION=""
declare _DEFAULT_NFS_MOUNT_OPTS="-fstype=nfs,nfsvers=3,nolock,udp,soft,timeo=120,retrans=20,_netdev"
declare _DEFAULT_GLUSTER_MOUNT_OPTS="-fstype=glusterfs"
declare CONTAINER_MOUNTS_STORAGE="/etc/autofs.jelastic"
declare _IPLIST
declare -a UNKNOWN_ARG
declare SAVE_CONFIG="true"

declare TRUE=0
declare FALSE=1

FORCE_UMOUNT=$TRUE
FORCE_MOUNT=$FALSE

STORAGE_BACKEND="nfs" # nfs | gluster

MOUNTPROG="/usr/sbin/automount"
MOUNTPROG_APK="/sbin/mount.nfs"
MOUNTPACKAGE="/var/lib/jelastic/packages/jelastic-nfs-utils.tar.gz"
_UI_RESULT=0
USERID=0
GROUPID=0
VERBOSE=1
DEFAULT_AUTOFS_TIMEOUT=300
JELASTIC_AUTOFS_TIMEOUT=3
NOLOCK=0

EXEC="/bin/bash -c "
SED_COPY_OPTION='--copy'

function doUsage() {
    showUsageMessage
}

function onModLoadCallback() {
    log "Preload callback";

    ## TODO: remove "params" garbarge option
    local temp=`getopt -o c:,s:,d:,u:,g:,l:,m: -l ctid:,source:,destination:,ip:,uid:,gid:,movedata:,saveconfig:,force:,cluster:,uuid:,vtype:,backend:,nolock: -- "$@" 2>/dev/null`;
    [[ $? != 0 ]] && die -q "Terminating...";
    eval set -- "$temp";

    while true ; do
        case "$1" in
            --force)
                shift;
                FORCE_UMOUNT=$TRUE
                FORCE_MOUNT=$TRUE
                shift;
                ;;
            --saveconfig)
                shift;
                SAVE_CONFIG=${1,,}
                shift;
                ;;
            -c | --ctid)
                shift;
                _CTID=$1
                CTID=$1
                shift;
                ;;
            --uuid)
                shift;
                _UUID=$1
                UUID=$1
                shift;
                ;;
            --vtype)
                shift;
                VTYPE=$1
                shift;
                ;;
            --cluster)
                shift;
                CLUSTER=$1
                if [ "x$CLUSTER" != "xtrue" ]; then
                    JELASTIC_AUTOFS_TIMEOUT="300"
                fi
                shift;
                ;;
            -s | --source)
                shift;
                _SOURCE=$1
                shift;
                ;;
            -d | --destination)
                shift;
                _DESTINATION=$1
                shift;
                ;;
            -l | --ip )
                shift;
                _IPLIST=$1;
                shift;
                ;;
            -m | --movedata)
                shift;
                _MOVEDATA=$1;
                shift;
                ;;
            -u | --uid)
                shift;
                USERID=$1;
                shift;
                ;;
            -g | --gid)
                shift;
                GROUPID=$1;
                shift;
                ;;
            --backend)
                shift;
                STORAGE_BACKEND=${1,,};
                shift;
                if [ "x$STORAGE_BACKEND" != "xgluster" -a "x$STORAGE_BACKEND" != "xnfs" ] ; then
                    STORAGE_BACKEND="nfs"
                fi
                ;;
            --nolock)
                shift;
                if [ "x$NOLOCK" != "xtrue" ]; then
                    NOLOCK=1
                else
                    NOLOCK=0
                fi
                shift;
                ;;
            --)
                shift;
                break;
                ;;
        esac;
    done;

    if [[ "$VTYPE" == VM ]]; then
        EXEC="$PRLCTL exec ${UUID}"
        vzexecSetENVID ${UUID}
        VEID=${UUID}
        isVMexist $UUID || { writeJSONResponseErr "result=>4003" "message=>uuid $UUID not found"; die -q; };
    else
        EXEC="$VZCTL exec2 ${CTID}"
        vzexecSetCTID ${CTID}
        VEID=${CTID}
        vzIsContainerExists $CTID || { writeJSONResponseErr "result=>4003" "message=>ctid $CTID not found"; die -q; };
    fi

    if [ -n "$VEID" ] ; then
        populateVEVarsVZ $VEID
        res=$?
        if [[ "$res" -eq 3 ]] ; then
            writeJSONResponseErr "result=>4003" "message=>ctid $CTID not found"
            die -q;
        fi

        if VEExecRun "sed -rne '/JELASTIC_CHECK_MOUNT=/{s/JELASTIC_CHECK_MOUNT=([0-9])/\1/g;p}' /.jelenv" ; then
            res=$(vzexecGetLastStdOut)
            [ -n "$res" ] && JELASTIC_CHECK_MOUNT=$res
        fi

        if [ "x$VZ_VEID_OS" == "xubuntu" -o "x$VZ_VEID_OS" == "xdebian" ] ; then
            SED_COPY_OPTION=''
        fi
    else
        SED_COPY_OPTION=''
    fi

    if [[ -n "$UUID" && "$VTYPE" == VM ]] ; then
        VE_ROOT="/vz/tmp/${UUID}"
    else
        #fallback to old var
        VE_ROOT=$VZ_VEID_ROOT
    fi

    for arg do UNKNOWN_ARG+=("$arg") ; done
    [[ ! -z "${VEID}" ]] && {
        MOUNTS_STORAGE="${VE_ROOT}${CONTAINER_MOUNTS_STORAGE}"
    }
    log "${UNKNOWN_ARG[*]}"
    return 0
}

function _hasActiveMounts() {
    #-hosts is /net/host
    #dir:path -> /path/*
    _cmd='[ -f /etc/auto.master ] && sed -re "/^#/d" -e "s/dir:(.*)/+ \1\/*/g" -e "/\s/!d" -e "s/-hosts/\/net\/host/g" /etc/auto.master | awk "{print $2}"'
    VEExecRun "$_cmd"
    autoFSMaps=($(VEexecGetLastStdOut))
    if [ -n "$autoFSMaps" ] ; then
        for f in ${autoFSMaps[*]} ; do
            #skipping also cdrom. it is not available in jelastic vzcontainers
            VEExecRun "[ -f \"$f\" ] && sed -re '/^#/d' -e '/^$/d' -e '/\/dev\/cdrom/d' $f"
            [ -n "$(VEexecGetLastStdOut)" ] && return 0
        done
    fi
    return 1
}

function _reloadAutoFS() {
    local _cmd="systemctl reload autofs || service autofs reload"
    VEExecRun "$_cmd" && return 0

    _cmd="pgrep automount >/dev/null && kill -s SIGHUP $(pidof -s automount)"
    VEExecRun "$_cmd"
    return $?
}

function _restartAutoFS() {
    local _cmd="systemctl restart autofs || service autofs restart"
    VEExecRun "$_cmd"
    return $?
}

function getTargetIPs() {
    isUUID $VEID && {
        VEExecRunInteractive "ip -o addr" | awk '!/^[0-9]*: ?lo|link\/ether/ {split($4,a,"/"); print a[1]}'
    } || {
        $AWK '/[ \t]*'${VEID}'/{$1=$2=$3="";gsub(/^[ \t]+/,"",$0);print $0}' /proc/vz/veinfo
    }
}

function preparePath() {
    local tpath=${1:?"Path required"}
    local hn=${2}

    isVERunning $VEID; _running=$?

    if [[ ! -z "$hn" ]] ; then
        [[ $_running -eq 0 ]] || tpath="$VZ_VEID_ROOT$tpath"
        tpath=$($SED -re 's/\$/\\$/g' -e 's/(`)/\\\1/g' <<< "${tpath}")
    fi

    local cmd="[[ -d '$($SED -re "s/'/\\\'\'/g" <<< "${tpath}")' ]] || { mkdir -p \"$($SED -re 's/"/\\\"/g' <<< "${tpath}")\" 2>/dev/null && chmod 0777 \"$($SED -re 's/"/\\\"/g' <<< "${tpath}")\";}";
    if [[ $_running -eq 0 ]] ; then
        VEExecRun "$cmd"
        return $(VEexecGetLastErrCode)

    fi

    /bin/bash -c "$cmd"
    return $?

}

function remountPath() {
    local share=$1
    local remountCmd="umount -l \"$share\" ; mount \"$share\""
    out=$(VEExecRunInteractive "$remountCmd" 2>&1)
    if [[ -z "${out}" ]] ; then
       log "$out"
    fi
    return $?
}

function checkMount() {
    #skip check if VEID is empty
    [[ -z "${VEID}" ]] && return 0

    if [ -z "$JELASTIC_CHECK_MOUNT" ]; then
        if ! VEExecRun "rpcinfo -p $1 | grep -q mountd" ; then
            log "mountd procedures not found on RPC server. Checking remote share will be disabled"
            JELASTIC_CHECK_MOUNT=0
        fi
        JELASTIC_CHECK_MOUNT=1
    fi

    case "$JELASTIC_CHECK_MOUNT" in
       false|0)
            log "remote server checking disabled for VEID $VEID"
            return 0
            ;;
        true|1)
            log "remote server checking enabled for VEID $VEID"
            ;;
    esac

    retries=5
    cmdShowmount='showmount -e '$1' | grep -P "^'$2'\s"'

    localCIPs=($(getTargetIPs))

    while [[ $retries -gt 0 ]] ; do
        #get IPs from remote storage
        VEExecRun $cmdShowmount
        ipsWODir="$(VEexecGetLastStdOut)"
        sharedIPs=($(awk '{split($1,a,",") ; if (a[1] != $0) { for (k in a) { if (a[k] != "") { print a[k] } } } else {print $2}}' <<< "${ipsWODir//$2/}"))

        #is local IP in remote network range
        for lIP in ${localCIPs[@]} ; do
            for sIP in ${sharedIPs[@]} ; do
                [[ "x$sIP" == "x*" || "x$sIP" == "x(everyone)" ]] && return 0
                (( $(inSubnet $sIP $lIP) )) && return 0
            done
        done

        sleep 4
        retries=$((retries-1))
    done

    if [[ "$(VEexecGetLastErrCode)" -gt 0 ]]; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID: StdErr: $(VEexecGetLastStdErr) StdOut": $(VEexecGetLastStdOut) >> ${JEM_CALLS_LOG};
    fi

    echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID: timeout has elapsed" >> ${JEM_CALLS_LOG};
    return 1
}

function detectNFSVersions() {
    cmd='rpcinfo $1 | sed -rne "/nfs/{s/\s+[0-9]+([0-9])\s+.*/\1/g;p}" | sort -ur'
    if VEExecRun $cmd ; then
        echo "$(VEexecGetLastStdOut)"
    else
        echo "0"
    fi
}

function processnfs4() {
    _DEFAULT_NFS_MOUNT_OPTS="-fstype=nfs,soft,timeo=30,retrans=2,_netdev"
    [[ $NOLOCK -eq 1 ]] && _DEFAULT_NFS_MOUNT_OPTS="$_DEFAULT_NFS_MOUNT_OPTS,nolock"
    processnfs "$@"
}

function processnfs3() {
    sourceIP=$1
    nfsVers=("3") #fallback in case of disabled mount check
    lproto="udp"

    case "$JELASTIC_CHECK_MOUNT" in
        true|1)
            if [ ! -z $sourceIP ] ; then
                nfsVers=($(detectNFSVersions $sourceIP))
            fi
            ;;
        false|0)
            nfsVers=("3")
            ;;
    esac

    if [[ "x${nfsVers[0]}" == "x3" ]] ; then
        lproto="tcp"
    fi

    _DEFAULT_NFS_MOUNT_OPTS="-fstype=nfs,nfsvers=3,nolock,$lproto,soft,timeo=120,retrans=20,_netdev"
    processnfs "$@"
}

function processnfs() {
    local sourceIP=${1:?"Source address required"}
    local sourceMount=${2:?"Source share name required"}
    local sourceMountUnEsc=$($SED -re 's/\\(\/|\(|\)|\]|\[|\\)/\1/g' <<< "$sourceMount")
    local destinationEsc=$($SED -re 's/\s/\\\\040/g' <<< "${_DESTINATION}" )
    local running

    isVERunning ${VEID} ; running=$?
    if [[ $running -ne 0 ]] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID - VE is not running." >> ${JEM_CALLS_LOG}
        if ! mountVE ${VEID} $VE_ROOT > /dev/null 2>&1 ; then
            writeJSONResponseErr "result=>4195" "message=>Cannot mount VE:$VEID"
            log "Cannot mount VE:$VEID"
            return 1
        fi
    fi

    OS=$VZ_VEID_OS
    OS_ver=$VZ_VEID_OS_VER

    if [[ "x$VZ_VEID_OS" == "xalpine" ]] ; then
        echo "echo `date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : Alpine Linux detected. " >> ${JEM_CALLS_LOG}

        if VEExecRun "[[ ! -e \"$MOUNTPROG_APK\" ]]" ; then
            if ! dosetupUtils ; then
                echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : Error installing utils $(gatherCTInfo) " >> ${JEM_CALLS_LOG}
                return 2
            fi
        fi

        [[ ! -z "${CTID}" ]] && {
            MOUNTS_STORAGE="$(vzctPath $VE_ROOT /etc/fstab)"
        }

        _DEFAULT_NFS_MOUNT_OPTS="$($SED -re 's/-fstype=nfs,//g' <<< $_DEFAULT_NFS_MOUNT_OPTS)"
        mntEntry="${sourceIP}:$($SED -re 's/\\\$/$/g' <<< "${sourceMountUnEsc}")\t${destinationEsc}\tnfs\t${_DEFAULT_NFS_MOUNT_OPTS}\t0\t0"
        #cmdRegisterMount="echo -e \"$mntEntry\" >> ${MOUNTS_STORAGE};"

    else
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : looking for $CONTAINER_MOUNTS_STORAGE " >> ${JEM_CALLS_LOG}
        isConfigDefined=1
        if [ $running -eq 0 -a "x$VTYPE" == "xVM" ] ; then
            grep -q "$CONTAINER_MOUNTS_STORAGE" <<< "$(VEExecRunInteractive cat /etc/auto.master 2>/dev/null)" 2>&1
            isConfigDefined=$?
        else
            grep -q "$CONTAINER_MOUNTS_STORAGE" "$(vzctPath $VZ_VEID_ROOT /etc/auto.master)" 2>&1
            isConfigDefined=$?
        fi

        if [[ $isConfigDefined -ne 0 ]] ; then
            echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : installing storage utils " >> ${JEM_CALLS_LOG}
            dosetupUtils || return 2
        fi

        autofsdest="$($SED -e 's/\s/\\ /g' <<< $_DESTINATION)"
        mntEntry="$autofsdest ${_DEFAULT_NFS_MOUNT_OPTS},uid=${USERID},gid=${GROUPID} ${sourceIP}:$($SED -re 's/\\\$/$/g' <<< "${sourceMountUnEsc}")"
        #cmdRegisterMount="echo -e \"$mntEntry\" >> ${MOUNTS_STORAGE}"
    fi

    if [[ $running -eq 0 ]] ; then
        if ! checkMount $sourceIP "$sourceMountUnEsc" ; then
            echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : Destination NFS server is not reachable. $(gatherCTInfo)" >> ${JEM_CALLS_LOG}
            echo "Destination NFS server is not reachable. Server IP: $(VEExecRunInteractive host ${sourceIP} 2>/dev/null), Client IP: $($AWK '/[ \t]*'${VEID}'/{$1=$2=$3="";gsub(/^[ \t]+/,"",$0);print $0}' /proc/vz/veinfo )"
            return 1
        fi
    fi

    if ! preparePath "${_DESTINATION}" "${VEID}" ; then
        echo "Cannot create path ${_DESTINATION}"
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : Cannot create path ${_DESTINATION}. $(gatherCTInfo)" >> ${JEM_CALLS_LOG}
        return 1
    fi

    if [[ "x$SAVE_CONFIG" == "xtrue" ]] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : registering ${sourceIP}:${sourceMount} in ${VEID}" >> ${JEM_CALLS_LOG}
        if ! [[ $running == 0 && "$VTYPE" == VM ]]; then
            out=$(echo -e $mntEntry >> ${MOUNTS_STORAGE})
        else
            VEExecRun "echo -e $mntEntry >> ${MOUNTS_STORAGE##"$VZ_VEID_ROOT"}"
            out=$(vzexecGetLastStdOut)
        fi
        if [[ ! -z "${out}" ]] ; then
            echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : $out" >> ${JEM_CALLS_LOG}
        fi
    fi

    msg=""
    res=0

    if [[ "x$VZ_VEID_OS" == "xalpine" ]] ; then
        if [[ $running -eq 0 ]] ; then
            mntcmd="mount \"$($SED -re 's/("\*|\$|\?|\|\^|`|'\'')/\\\1/g' <<< "${_DESTINATION}")\""
            VEExecRun "${mntcmd}"
            res="$(VEexecGetLastErrCode)"
            msg="$(VEexecGetLastStdErr)"
            if [[ $res -gt "0" ]] && [[ $FORCE_MOUNT -eq $FALSE ]] ; then
                local mntEntryCheck="${sourceIP}:$($SED -re 's/(\$|\[|\]|\*|\(|\)|\?|\||\^)/\\\1/g' -e 's/\\\\\$/$/g' <<< ${sourceMount})/? on $($SED -re 's/(\[|\]|\*|\(|\)|\$|\?|\||\^|`)/\\\1/g' <<< ${destinationEsc})"
                VEExecRun "mount | $GREP -P \"$mntEntryCheck\""
                res=$(VEexecGetLastErrCode)
                if [[ $res -ne $TRUE ]] ; then
                    #remove the /etc/fstab entry
                    cmdUnregisterMount="/$(echo -e $mntEntry | $SED -r -e 's/\t/\\\s+/g;' -e 's/\//\\\//g' -e 's/\./\\./g' -e 's/(\[|\]|\*|\(|\)|\$|\?|\||\^)/\\\1/g')/d"
                    if [[ "x$SAVE_CONFIG" == "xtrue" ]] ; then
                        out=$($SED -i -re "$cmdUnregisterMount" ${MOUNTS_STORAGE} 2>&1)
                    fi
                    log $out
                    msg="${msg}. Server IP is: $(host ${sourceIP}), RPC connection: $(timeout 1 bash -c "cat < /dev/null > /dev/tcp/${sourceIP}/111" 2>/dev/null; echo $?)"
                    echo "echo `date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : Error mounting share. $(gatherCTInfo)" >> ${JEM_CALLS_LOG}
                    res=4111
                else
                    res=0
                fi
            fi
        fi
        [[ -z "$msg" ]] && echo "successfuly mounted" || echo $msg
        [[ "$res" -gt 0 ]] && return 1;
    fi

    if [[ $running -eq 0 ]] ; then
        if _hasActiveMounts ; then

            VEExecRun "$_ENABLEAUTOFSCMD"
            if [[ "x$SAVE_CONFIG" == "xfalse" ]] ; then
                _restartAutoFS
            else
                _reloadAutoFS
            fi
        else
            VEExecRun "$_DISABLEAUTOFSCMD"
        fi
    else
        log "unmounting"
        umountVE ${VEID} "$VE_ROOT" >> ${JEM_CALLS_LOG} 2>&1
    fi
    [[ -z "$msg" ]] && echo "successfuly mounted" || echo $msg
    [[ "$res" -gt 0 ]] && return 1;
    return 0
}

function checkUtils() {
    if isUUID $VEID; then
      #check only on running VM
      [ -z "$VZ_VEID_ROOT" ] && return 1
      isVERunning $VEID || return 1

      #check for jelastic's autofs config
      VEExecRun "[ -e $VZ_VEID_ROOT/etc/autofs.gluster ]"
      [[ "$(VEexecGetLastErrCode)" != "0" ]] && return 1

      #check for gluster helper
      VEExecRun "[ ! -x $VZ_VEID_ROOT/usr/sbin/mount.glusterfs -a ! -x $VZ_VEID_ROOT/sbin/mount.glusterfs ]"
      [[ "$(VEexecGetLastErrCode)" == "0" ]] && return 1
    else
      #check only on mounted or running container
      [ -z "$VZ_VEID_ROOT" ] && return 1
      isContainerMounted $CTID || return 1

      #check for jelastic's autofs config
      if [ ! -e "$VZ_VEID_ROOT/etc/autofs.gluster" ] ; then
          return 1
      fi

      #check for gluster helper
      if [ ! -x "$VZ_VEID_ROOT/usr/sbin/mount.glusterfs" -a ! -x "$VZ_VEID_ROOT/sbin/mount.glusterfs" ] ; then
          return 1
      fi
    fi
    return 0
}

function processgluster() {
    CONTAINER_MOUNTS_STORAGE='/etc/autofs.gluster'
    STORAGE_BACKEND="gluster"

    #check if client available
    if isVERunning $VEID ; then
        if ! VEExecRun "command -v mount.glusterfs &>/dev/null" ; then
            echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID glusterfs helper not found. Installing..." >> $JEM_CALLS_LOG
            dosetupUtils || return 2
        fi
    else
        if ! checkUtils $CTID ; then
            echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID - container is not running. Missing utilities" >> $JEM_CALLS_LOG
            writeJSONResponseErr "result=>4207" "message=>Cannot setup gluster native client. Container is stopped"
            return 2
        fi
    fi

    local sourceMountUnEsc=$(sed -re 's/\\(\/|\(|\)|\]|\[|\\)/\1/g' <<< "$sourceMount")
    local destinationEsc=$(sed -re 's/\s/\\\\040/g' <<< "$_DESTINATION" )

    [[ ! -z "$VEID" ]] && {
        MOUNTS_STORAGE="${VE_ROOT}${CONTAINER_MOUNTS_STORAGE}"
    }

    if [[ $running -ne 0 ]] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID - container is not running." >> $JEM_CALLS_LOG
        $VZCTL mount $CTID > /dev/null 2>&1
    fi

    if [[ "x$VZ_VEID_OS" == "xalpine" ]] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : Alpine Linux detected. Glusterfs is not supported for it" >> $JEM_CALLS_LOG
        writeJSONResponseErr "result=>4207" "message=>Cannot setup gluster native client"
        return 2
    fi

    if ! VEExecRun "command -v mount.glusterfs &>/dev/null" ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction CTID:$CTID glusterfs helper not found. Installing..." >> ${JEM_CALLS_LOG}
        dosetupUtils || return 1
    fi

    autofsdest="$(sed -e 's/\s/\\ /g' <<< $_DESTINATION)"
    mntEntry="$autofsdest $_DEFAULT_GLUSTER_MOUNT_OPTS $sourceIP:/$(sed -re 's/\\\$/$/g' <<< "$sourceMountUnEsc")"
    #cmdRegisterMount="echo -e \"$mntEntry\" >> $MOUNTS_STORAGE"

    if ! preparePath "$_DESTINATION" "$VEID" ; then
        echo "Cannot create path $_DESTINATION"
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : Cannot create path $_DESTINATION. $(gatherCTInfo)" >> $JEM_CALLS_LOG
        return 1
    fi

    if [[ "x$SAVE_CONFIG" == "xtrue" ]] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : registering $sourceIP:$sourceMount in $VEID" >> $JEM_CALLS_LOG
        if ! [[ $running == 0 && "$VTYPE" == VM ]]; then
            out=$(echo -e $mntEntry >> $MOUNTS_STORAGE)
        else
            VEExecRun "echo -e $mntEntry >> ${MOUNTS_STORAGE##"$VE_ROOT"}"
            out="$(VEexecGetLastStdOut)";
        fi
        if [[ ! -z "$out" ]] ; then
            echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : $out" >> $JEM_CALLS_LOG
        fi
    fi

    if [[ $running -eq 0 ]] ; then
        if _hasActiveMounts ; then
            VEExecRun "$_ENABLEAUTOFSCMD"
            if [[ "x$SAVE_CONFIG" == "xfalse" ]] ; then
                _restartAutoFS
            else
                _reloadAutoFS
            fi
        else
            VEExecRun "$_DISABLEAUTOFSCMD"
        fi
    else
        log "unmounting"
        umountVE ${VEID} "$VE_ROOT" >> ${JEM_CALLS_LOG} 2>&1
    fi

    echo "successfuly mounted"
    return 0
}

function processlocal() {
    CONTAINER_MOUNTS_STORAGE="/etc/fstab"
    log "source: $sourceMount destination: ${_DESTINATION} veid: ${VEID}"
    local mntEntry="${sourceMount}\t${_DESTINATION}\tnone\trw,bind\t0\t0"

    if [ -z "$VEID" ] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : there is no VEID. Local mounts available only via hardnode call $(gatherCTInfo)" >> ${JEM_CALLS_LOG}
        echo "VEID required"
        return 1;
    fi

    isVERunning ${VEID} ; running=$?
    if [[ $running -ne 0 ]] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID - VE is not running." >> ${JEM_CALLS_LOG}
        if ! mountVE ${VEID} $VE_ROOT > /dev/null 2>&1 ; then
            writeJSONResponseErr "result=>4195" "message=>Cannot mount VE:$VEID"
            log "Cannot mount VE:$VEID"
            return 1
        fi
    fi

    OIFS=${IFS};IFS=$'\n'
    if [[ $running == 0 && "$VTYPE" == VM ]]; then
        local aCurrentMounts=($($SED -nre "/none/{/bind/{s/\s*(\S+).*/\1/;p}}" <<<"$(VEExecRunInteractive cat $CONTAINER_MOUNTS_STORAGE)"))
    else
        local aCurrentMounts=($($SED -nre "/none/{/bind/{s/\s*(\S+).*/\1/;p}}" "$(vzctPath $VE_ROOT $CONTAINER_MOUNTS_STORAGE)"))
    fi


    IFS=${OIFS}

    log "${aCurrentMounts[@]}"

    if [[ ${#aCurrentMounts[@]} -gt 0 ]] ; then
        if indexOf "${aCurrentMounts[*]}" "${sourceMount}" >/dev/null; then
            echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : ${sourceMount} already mounted" >> ${JEM_CALLS_LOG}
            echo "already mounted"
            if [[ $running -ne 0 ]] ; then
                log "unmounting"
                umountVE ${VEID} "$VE_ROOT" >> ${JEM_CALLS_LOG} 2>&1
            fi
            return 0;
        fi
    else
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : cannot get fstab entries" >> ${JEM_CALLS_LOG}
    fi

    if ! preparePath "${_DESTINATION}" 1 ; then
        echo "Cannot create path ${_DESTINATION}"
        return 1
    fi
    if ! preparePath "${sourceMount}" 1 ; then
        echo "Cannot create path ${sourceMount}"
        return 1
    fi

    hnSrcPath=${sourceMount}
    hnDstPath=${_DESTINATION}

    if [[ "$_MOVEDATA" -gt 0 ]] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : moving data from $hnDstPath to $hnSrcPath" >> ${JEM_CALLS_LOG}
        if ! [[ $running == 0 && "$VTYPE" == VM ]]; then
            if [[ "$VEID" != 0 ]] ; then
                hnDstPath="${VE_ROOT}${hnDstPath}"
                hnSrcPath="${VE_ROOT}${hnSrcPath}"
            fi
            $RSYNC -aP --force "${hnDstPath}/" "${hnSrcPath}/" >> $ACTIONS_LOG 2>&1
            rm -fr "${hnDstPath}/*" >> $ACTIONS_LOG 2>&1
        else
            VEExecRun "rsync -aP --force \"${hnDstPath}/\" \"${hnSrcPath}/\" 2>&1"
            VEexecGetLastStdOut >> $ACTIONS_LOG
            VEExecRun "rm -fr \"${hnDstPath}/*\" 2>&1"
            VEexecGetLastStdOut >> $ACTIONS_LOG
        fi
    fi

    if ! [[ $running == 0 && "$VTYPE" == VM ]]; then
        echo -e $mntEntry >> "${VE_ROOT}${CONTAINER_MOUNTS_STORAGE}"
    else
        VEExecRun "echo -e $mntEntry >> \"${CONTAINER_MOUNTS_STORAGE}\""
    fi
    echo $mntEntry
    if [[ $running -eq 0 ]] ; then
        VEExecRun "mount \"$($SED -re 's/("\*|\$|\?|\|\^|`|'\'')/\\\1/g' <<< "${_DESTINATION}")\""
    else
        umountVE ${VEID} "$VE_ROOT" >> ${JEM_CALLS_LOG} 2>&1
    fi
    res=$?
    if [[ $res -gt 0 ]]; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : error mounting share $(gatherCTInfo)" >> ${JEM_CALLS_LOG}
        return 1;
    fi
    if [[ $running -ne 0 ]] ; then
        log "unmounting"
        umountVE ${VEID} "$VE_ROOT" >> ${JEM_CALLS_LOG} 2>&1
    fi
    return 0;
}

function doRemount() {
    if [[ "x$VZ_VEID_OS" == "xalpine" ]] ; then
        log "OS is ALPINE"
        local shares=(${_DESTINATION})
        [[ -z ${_DESTINATION} ]] && {
            [[ ! -z "${VEID}" ]] && MOUNTS_STORAGE="$(vzctPath $VZ_VEID_ROOT /etc/fstab)"
            shares=($($SED -nre "/\snfs(3|4)?\s/{s/\s*(\S+)\s*(\S+).*/\2/;p}" "$MOUNTS_STORAGE" ))
        }
        for share in ${shares[*]} ; do
            remountPath "$share"
        done
        return 0
    fi

    isVERunning ${VEID} ; running=$?

    if [[ $running -eq 0 ]] ; then
        if _hasActiveMounts ; then
            VEExecRun "$_ENABLEAUTOFSCMD"
            _reloadAutoFS
        else
            VEExecRun "$_DISABLEAUTOFSCMD"
        fi
    fi

    return 0;
}

function dosetupUtils() {

    if [[ "x$VEID" == "x" ]] ; then
        writeJSONResponseErr "result=>4140" "message=>Failed to install packages: CTID is required"
        return 1
    fi

    if ! isVERunning $VEID ; then
        writeJSONResponseErr "result=>4110" "message=>Cannot execute command. Container is not running"
        return 1
    fi

    OS=$VZ_VEID_OS
    OS_ver=$VZ_VEID_OS_VER

    #JE-25896
    if [[ "x$OS" == "xalpine" ]] ; then
        if [[ "$STORAGE_BACKEND" == "gluster" ]] ; then
            writeJSONResponseErr "result=>4112" "message=>NFS: Alpine Linux is not supported"
            return 1
        fi
        installCmd=$(installPackageCmd $OS install nfs-utils)
        VEExecRun "$installCmd"

        checkCmd=$(checkPackageCmd $OS nfs-utils)
        VEExecRun "eval $checkCmd"
        stdout=$(VEexecGetLastStdOut)
        if [[ -n "$stdout" ]] ; then
            writeJSONResponseErr "result=>4140" "message=>Failed to install following packages: $stdout"
            return 1
        fi

        VEExecRun "rc-update add netmount default"
        return 0
    fi

    [[ "$STORAGE_BACKEND" == "nfs" ]] && _packages="autofs nfs-utils"
    [[ "$STORAGE_BACKEND" == "gluster" ]] && _packages="autofs glusterfs-fuse"

    if [ "x$OS" == "xubuntu" -o "x$OS" == "xdebian" ] ; then
        VEExecRun "apt update"

        dc=3
        de=0
        packageName="autofs_5.1.6-1j_amd64.deb"

        while [[ $dc -gt 0 ]] ; do
            VEDownloadFileWMD5 "http://repository.jelastic.com/pub/$packageName"
            de=$?
            dc=$((dc-1))
        done

        if [[ $de -ne 0 ]] ; then
            writeJSONResponseErr "result=>4140" "message=>Failed to install following packages: $packageName. Downloading error!"
        fi

        if [ "x$OS" == "xdebian" -a "$OS_ver" -eq "8" ]; then
            VEExecRun "$(installPackageCmd $OS install autofs)"
            VEExecRun "DEBIAN_FRONTEND=noninteractive dpkg -i ./$packageName"
        else
            VEExecRun "$(installPackageCmd $OS install ./$packageName)"
        fi
        VEExecRun "rm -f $packageName"
        if [[ "$STORAGE_BACKEND" == "gluster" ]] ; then
            if [ "x$OS" == "xubuntu" ] ; then
                #Ubuntu
                VEExecRun "add-apt-repository ppa:gluster/glusterfs-7 -y"
            else
                #Debian
                if [ "$OS_ver" -eq "8" ] ; then
                    writeJSONResponseErr "result=>4112" "message=>Gluster: Debian 8 GNU/Linux is not supported"
                    return 1
                fi

                local _code_name="bullseye" # Debian 11
                [ "$OS_ver" -eq "9"  ] && _code_name="stretch"
                [ "$OS_ver" -eq "10" ] && _code_name="buster"

                VEExecRun "wget -O - https://download.gluster.org/pub/gluster/glusterfs/7/rsa.pub | apt-key add -"
                VEExecRun "[ ! -d /etc/apt/sources.list.d ] && mkdir -p /etc/apt/sources.list.d"
                VEExecRun "echo deb [arch=amd64] https://download.gluster.org/pub/gluster/glusterfs/7/LATEST/Debian/$_code_name/amd64/apt $_code_name main > /etc/apt/sources.list.d/gluster.list"
                VEExecRun "apt install apt-transport-https -y"
            fi
            VEExecRun "apt-get update -y"

            installCmd="$(installPackageCmd $OS install glusterfs-client)"
            checkCmd=$(checkPackageCmd $OS autofs glusterfs-client)
        else
            installCmd="$(installPackageCmd $OS install nfs-common)"
            checkCmd=$(checkPackageCmd $OS autofs nfs-common)
        fi
    elif [[ "$OS" == "centos" || "$OS" == "almalinux" ]] ; then
        _isCertified=0
        if [ "$OS_ver" -eq "8" ]; then
            _autofspkg="http://repository.jelastic.com/pub/autofs-5.1.6-1j.el8.x86_64.rpm"
        elif  [ "$OS_ver" -eq "9" ]; then
            _autofspkg="http://repository.jelastic.com/pub/autofs-5.1.8-1j.el9.x86_64.rpm"
            if vzexecRun "sed -rne '/CERTIFIED_VERSION=/{s/CERTIFIED_VERSION=([0-9]{1,})/\1/g;p}' /etc/jelastic/metainf.conf" ; then
                res=$(vzexecGetLastStdOut)
                CERTIFIED_VERSION=$res
                _isCertified="$CERTIFIED_VERSION"
                echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction CTID:$CTID - certified template version $_isCertified" >> ${JEM_CALLS_LOG};
                [[ _isCertified -ge 3 ]] && { vzexecRun "rpm -ivh $_autofspkg"; _autofspkg=""; }
            fi
        fi
        if [ "$OS_ver" -eq "7" ]; then
            _autofspkg="http://repository.jelastic.com/pub/autofs-5.1.6-1j.el7.x86_64.rpm"
        fi

        if [[ "$STORAGE_BACKEND" == "gluster" ]] ; then
            installCmd=$(installPackageCmd $OS install $_isCertified $_autofspkg glusterfs-fuse)
        else
            installCmd=$(installPackageCmd $OS install $_isCertified $_autofspkg nfs-utils)
        fi
        checkCmd=$(checkPackageCmd $OS $_packages)
    else
        installCmd=$(installPackageCmd $OS install $_packages)
        checkCmd=$(checkPackageCmd $OS $_packages)
    fi
    VEExecRun "$installCmd"
    echo "$(VEexecGetLastStdOut)" >> ${ACTIONS_LOG}

    VEExecRun "eval $checkCmd"
    stdout=$(VEexecGetLastStdOut)
    if [[ -n "$stdout" ]] ; then
        writeJSONResponseErr "result=>4140" "message=>Failed to install following packages: $stdout"
        return 1
    fi

    VEExecRun '[ -e /etc/rc.d/init.d/autofs ]'
    if [[ "$(VEexecGetLastErrCode)" == 0 ]]; then
        VEExecRunInteractive "grep killproc -A2 /etc/rc.d/init.d/autofs" | $GREP -q 'sleep 1' || \
            VEExecRunInteractive "sed -i '/killproc/{N;s/$/\n\t\tsleep 1;/}' /etc/rc.d/init.d/autofs"
    fi

    VEExecRun '[ -e /etc/autofs.conf ]'
    if [[ "$(VEexecGetLastErrCode)" == 0 ]]; then
        VEExecRunInteractive "sed -i $SED_COPY_OPTION -e \"s/^timeout = .*/timeout = ${JELASTIC_AUTOFS_TIMEOUT}/g\" /etc/autofs.conf"
    fi

    if [ "x$OS" == "xdebian" -a "$OS_ver" -eq "7" ] ; then
        VEExecRun '[ -e /etc/init.d/autofs) ]'
        if [[ "$(VEexecGetLastErrCode)" == 0 ]]; then
            VEExecRunInteractive "sed -i -re 's/PROG=automount/PROG=automount\n_SYSTEMCTL_SKIP_REDIRECT=\"true\"/' /etc/init.d/autofs"
        fi
    fi

    if [ "x$OS" == "xcentos" -a "$OS_ver" -eq "7" ] ; then
        VEExecRun "sed -i -re '/automount/d' /etc/nsswitch.conf"
        VEExecRun 'echo -e "\nautomount:  files" >> /etc/nsswitch.conf'
    fi
    if [[ "$STORAGE_BACKEND" == "gluster" ]] ; then
        VEExecRun "echo '/- /etc/autofs.gluster --timeout=3600' >> /etc/auto.master"
    else
        VEExecRun "echo '/- /etc/autofs.jelastic' >> /etc/auto.master"
    fi
    VEExecRun "$_DISABLEAUTOFSCMD"
    return 0
}

function gatherCTInfo() {
    isVERunning $VEID || {
        echo "VE $VEID is not running"
    }

    local _autoFSCfg
    [[ -n "$CONTAINER_MOUNTS_STORAGE" ]] && _autoFSCfg=$CONTAINER_MOUNTS_STORAGE || _autoFSCfg=${MOUNTS_STORAGE##"$VE_ROOT"}

    _ctAutoFSFile="$(VEExecRun " [ -e \"$_autoFSCfg\" ] && cat \"$_autoFSCfg\" || echo \"$_autoFSCfg not found\""; VEexecGetLastStdOut)"
    _ctFstab="$(VEExecRun " [ -e \"/etc/fstab\" ] && cat /etc/fstab || echo \"/etc/fstab not found\""; VEexecGetLastStdOut)"
    _ctIptablesRules="$(VEExecRun "iptables -S"; VEexecGetLastStdOut)"
    _ctIpInfo="$(VEExecRun "ip a l; ip r l; [ -e /etc/resolv.conf ] && cat /etc/resolv.conf || echo /etc/resolv.conf" ; VEexecGetLastStdOut)"
    _ctnftablesrules="$(VEExecRun "[ -x /usr/sbin/nft ] && nft -s list ruleset")"

    echo -e "\n`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID \n=====\nContainer $VEID Info:\nautofs:\n$_ctAutoFSFile\nfstab:\n$_ctFstab\nip info:\n$_ctIpInfo\niptables:\n$_ctIptablesRules\n=====\nnft:\n$_ctnftablesrules\n======"
}

function doMount() {
    [[ -z ${_SOURCE} && -z ${_DESTINATION} ]] && {
        out=$($EXEC "mount -a" 2>&1)
        if [[ ! -z "${out}" ]] ; then
            log "$out"
        fi
        return 0;
    }
    [[ -z ${_SOURCE} ]] && {
        writeJSONResponseErr "result=>4065" "message=>SOURCE required" ;
        return 1;
    }
    [[ -z ${_DESTINATION} ]] && {
        writeJSONResponseErr "result=>4066" "message=>DESTINATION required" ;
        return 1;
    }

    local mtype sourceIP sourceMount
    isVERunning ${VEID} ; running=$?

    if [[ $running -ne 0 ]] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID - VE is not running." >> $JEM_CALLS_LOG
        if ! mountVE ${VEID} $VE_ROOT > /dev/null 2>&1 ; then
            writeJSONResponseErr "result=>4195" "message=>Cannot mount VE:$VEID"
            return 1
        fi
        [ -e "$(vzctPath $VZ_VEID_ROOT /etc/autofs.conf)" ] && $SED -i -e "s/^timeout = ${DEFAULT_AUTOFS_TIMEOUT}/timeout = ${JELASTIC_AUTOFS_TIMEOUT}/g" "$(vzctPath $VZ_VEID_ROOT /etc/autofs.conf)"
    else
        VEExecRun " [ -e \"/etc/autofs.conf\" ] && sed -i $SED_COPY_OPTION -e \"s/^timeout = ${DEFAULT_AUTOFS_TIMEOUT}/timeout = ${JELASTIC_AUTOFS_TIMEOUT}/g\" \"/etc/autofs.conf\""
    fi

    # parse connection string
    _SOURCE="$($SED -re 's/(\[|\]|\*|\(|\)|\$|\?|\|)/\\\1/g' <<< "$_SOURCE")"
    availProtos="[Ll][Oo][Cc][Aa][Ll]|[Nn][Ff][Ss]3?4?|[Ww][Ee][Bb][Dd][Aa][Vv]|[Gg][Ll][Uu][Ss][Tt][Ee][Rr]"
    availModes="[Rr][Oo]|[Rr][Ww]"
    eval "$(echo "${_SOURCE}" | \
        $SED -rne "s/(($availModes):?($availProtos):?(\/){0,2})?([^:]+):?(.*)/atype=\2\nmtype='\3'\nsourceIP='\5'\nsourceMount='\6';/g;p" | \
        $SED -re "s/='(.*?)'.*/=\1/g" | \
        $SED -re "s/('|\"|\`)/\\\\\1/g" | \
        $SED -re 's/(.*)=(.*)/\1="\2"/g')"

    mtype=${mtype,,}
    atype=${atype,,}
    atype=$($SED -re 's/;//g' <<< $atype)
    echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID - protocol=${mtype} source=${sourceIP} sourceMount=${sourceMount}" >> ${JEM_CALLS_LOG}
    [[ -z "${mtype}" ]] && mtype="nfs"

    # for local mounts (bind)
    if [ "${mtype}" == "local" -a "x${sourceMount}" == "x" ] ; then
        sourceMount="/${sourceIP}"
    fi
    [[ -z "${sourceMount}" ]] && mountpoint="/volumes"
    [[ -z "${sourceIP}" ]] && {
        writeJSONResponseErr "result=>4067" "message=>invalid source string format." ;
        return 1;
    }
    _DEFAULT_NFS_MOUNT_OPTS="${_DEFAULT_NFS_MOUNT_OPTS},${atype}"
    msg=$(process${mtype} "${sourceIP}" "${sourceMount}"); res=$?
    result="$res"
    if [[ $running -ne 0 ]] ; then
        umountVE ${VEID} "$VE_ROOT" >> ${JEM_CALLS_LOG} 2>&1
    fi
    [[ "$res" -gt 0 ]] && result="4111";
    [[ "$res" -eq 2 ]] && return 1
    writeJSONResponseOut "result=>$result" "message=>${msg}" ;
    return 0
}

function doUmount() {
    [[ -z ${_DESTINATION} && -z ${UNKNOWN_ARG} ]] && {
        writeJSONResponseErr "result=>4066" "message=>DESTINATION required" ;
        return 1;
    }
    local rescode retfunc msg="successfully unmounted";
    local running
    local -a shares

    isVERunning ${VEID}; running=$?
    if [[ $running -ne 0 ]] ; then
        echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID - VE is not running." >> $JEM_CALLS_LOG
        if ! mountVE ${VEID} $VE_ROOT > /dev/null 2>&1 ; then
            writeJSONResponseErr "result=>4195" "message=>Cannot mount VE:$VEID"
            return 1
        fi
    fi

    for i in $(seq 0 $((${#UNKNOWN_ARG[@]}-1))); do
        if [ ! -z "${UNKNOWN_ARG[$i]}" ] ; then
            [ ${#shares[*]} -gt 0 ] && shares=("${shares[@]}" "${UNKNOWN_ARG[$i]}") || shares=("${UNKNOWN_ARG[$i]}")
        fi
    done

    if [[ ! -z ${_DESTINATION} ]] ; then
        shares+=("${_DESTINATION}")
    fi

    if [[ "x$VZ_VEID_OS" == "xalpine" ]] ; then
        [[ ! -z "${CTID}" ]] && MOUNTS_STORAGE="$(vzctPath $VZ_VEID_ROOT /etc/fstab)"
    fi

    OIFS=$IFS; IFS=$'\n'
    for i in $(seq 0 $((${#shares[*]}-1)) ) ; do
        IFS=$OIFS
        if [[ $running -eq 0 ]] ; then
            if ! VEExecRun "umount '${shares[$i]}';" ; then
                echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID - Performing lazy umount of ${shares[$i]}" >> $JEM_CALLS_LOG
                if ! VEExecRun "umount -l '${shares[$i]}';" ; then
                    msg="$(VEexecGetLastStdErr)";
                else
                    msg="$(VEexecGetLastStdOut)";
                fi
            fi
            rescode=$(VEexecGetLastErrCode)
        else
            #Already mounted
            #mountVE ${VEID} $VE_ROOT > /dev/null 2>&1 || { writeJSONResponseOut "result=>4195" "message=>Cannot mount VE:$VEID" ;
            #    log "Cannot mount VE:$VEID";
            #    return 99; }
            rescode=0
        fi

        if [[ $FORCE_UMOUNT -eq 0 ]] ; then
             rescode=0
        fi

        if [[ "x$SAVE_CONFIG" == "xtrue" ]] ; then
            if [ $rescode -eq 0 ] ; then
                if [[ "x$VZ_VEID_OS" == "xalpine" ]] ; then
                    local dpath="\s+$($SED -re 's/\//\\\//g' <<< $($SED -re 's/\^/\\^/g' -e 's/\$/\\$/g' -e 's/(\+\{|\}|\[|\]|\(|\))/\\\1/g'  -e 's/\s/\\\\040/g' <<< "${shares[$i]}"))\s+(nfs|none)\s+";
                else
                    local dpath="^$($SED -re 's/\//\\\//g' <<< $($SED -re 's/\^/\\^/g' -e 's/\$/\\$/g' -e 's/(\+\{|\}|\[|\]|\(|\))/\\\1/g'  -e 's/\s/\\\\ /g' <<< "${shares[$i]}"))\s+-fstype=(nfs|glusterfs).*";
                fi
                if ! [[ $running == 0 && "$VTYPE" == VM ]]; then
                    out=$( [[ -e "$MOUNTS_STORAGE" ]] && $SED -i -re /"${dpath}"/d "$MOUNTS_STORAGE" 2>&1 )
                    out=$( [[ -e "${VE_ROOT}/etc/autofs.gluster" ]] && $SED -i -re /"${dpath}"/d "${VE_ROOT}/etc/autofs.gluster" 2>&1 )
                else
                    VEExecRun "[[ -e \"$CONTAINER_MOUNTS_STORAGE\" ]] && sed -i -re /\"${dpath}\"/d \"$CONTAINER_MOUNTS_STORAGE\" 2>&1"
                    out="$(VEexecGetLastStdOut)";
                    VEExecRun "[[ -e \"/etc/autofs.gluster\" ]] && sed -i -re /\"${dpath}\"/d \"/etc/autofs.gluster\" 2>&1"
                    out="$out $(VEexecGetLastStdOut)";
                fi
                [[ ! -z "${out}" ]] && log "${out}";
                retfunc="writeJSONResponseOut result=>0"
            else
                echo "`date +%D.%k:%M:%S.%N`:   $action:$subaction VEID:$VEID : error umounting share $(gatherCTInfo)" >> ${JEM_CALLS_LOG}
                retfunc="writeJSONResponseErr result=>99"
            fi
        else
            retfunc="writeJSONResponseOut result=>$rescode"
        fi
    done

    if [[ $running -ne 0 ]] ; then
        umountVE ${VEID} "$VE_ROOT" >> ${JEM_CALLS_LOG} 2>&1
    else
        if _hasActiveMounts ; then
            VEExecRun "$_ENABLEAUTOFSCMD"
            _reloadAutoFS
        else
            VEExecRun "$_DISABLEAUTOFSCMD"
        fi
    fi

    $retfunc "message=>$msg";
    return 0;
}

function doList() {
    msg=$($EXEC "mount | $SED -nre '/nfs(3|4)?/{s/(.*)\s+type.*/\1/g;p}';")
    writeJSONResponseOut "result=>0" "message=>$msg"
    return 0
}


function doExport() {
    [[ -z ${_SOURCE} ]] && {
        writeJSONResponseErr "result=>4065" "message=>SOURCE required" ;
        return 1;
    }

    if ! VEExecRun "jem auth add -t ip -l ${_IPLIST};" ; then
        writeJSONResponseErr "result=>4030" "message=>$(VEexecGetLastStdErr)";
        return $(VEexecGetLastErrCode);
    fi
    if ! VEExecRun "mkdir -p '${_SOURCE}'; chmod 0777 '${_SOURCE}';" ; then
        writeJSONResponseErr "result=>4030" "message=>$(VEexecGetLastStdErr)";
        return $(VEexecGetLastErrCode);
    fi
    if ! VEExecRun "exportfs -ra;" ; then
        writeJSONResponseErr "result=>4030" "message=>$(VEexecGetLastStdErr)";
        return $(VEexecGetLastErrCode);
    fi
    writeJSONResponseOut "result=>0" "message=>success";
    return 0;
}

function describeExport() {
    echo "Export";
}

function describeExportParameters() {
    echo "-o|--ctid <ctid> -s|--source <spath>";
}

function describeExportOptions() {
    echo "-s|--source: source path";
    echo "-o|--ctid: container ID";
}

function describeList() {
    echo "List mount points";
}

function describeListParameters() {
    echo "-o|--ctid <ctid>";
}

function describeListOptions() {
    echo "-o|--ctid: container ID";
}

function describeMount() {
    echo "Mount source to destination";
}

function describeMountParameters() {
    echo "-o|--ctid <ctid> --uuid <UUID> --vtype <vtype> -s||--source <spath> -d|--destination <dpath>";
}

function describeMountOptions() {
    echo "-o|--ctid: container ID";
    echo "--uuid: VM uuid";
    echo "--vtype: VE type: VM or CT";
    echo "-s|--source: source path";
    echo "-d|--destination: destination path";


}

function describeUmount() {
    echo "Umount destination";
}

function describeUmountParameters() {
    echo "-o|--ctid <ctid> --uuid <UUID> --vtype <vtype> -d|--destination  <dpath>";
}

function describeUmountOptions() {
    echo "-o|--ctid: container ID ";
    echo "--uuid: VM uuid";
    echo "--vtype: VE type: VM or CT";
    echo "-d|--destination: destination path";
}

defineBigInline _DISABLEAUTOFSCMD <<'EOF'
    if pgrep automount >/dev/null ; then
        if [ -d /run/systemd/system ] ; then
            systemctl disable autofs;
            systemctl stop autofs;
        elif command -V initctl >/dev/null 2>&1 ; then
            if command -V update-rc.d >/dev/null 2>&1 ; then
                update-rc.d autofs disable ;
            else
                chkconfig autofs off;
                service autofs stop ;
            fi;
        fi;
    else
        if [ -d /run/systemd/system ] ; then
            systemctl disable autofs;
        elif command -V initctl >/dev/null 2>&1 ; then
            update-rc.d autofs disable ;
        else
            chkconfig autofs off;
        fi
    fi
EOF

defineBigInline _ENABLEAUTOFSCMD <<'EOF'
    if [ -d /run/systemd/system ] ; then
        systemctl enable autofs;
        if ! pgrep automount >/dev/null ; then
            systemctl start autofs;
        fi
    elif command -V initctl >/dev/null 2>&1 ; then
        if command -V update-rc.d >/dev/null 2>&1 ; then
            update-rc.d autofs enable ;
        else
            chkconfig autofs on;
        fi
        if ! pgrep automount >/dev/null ; then
            service autofs start ;
        fi
    else
        chkconfig autofs on;
        if ! pgrep automount >/dev/null ; then
            service autofs start ;
        fi
    fi;
EOF

