ronivay / XenOrchestraInstallerUpdater

Xen Orchestra install/update script
GNU General Public License v3.0
1.14k stars 190 forks source link

Using a custom commit - "something went wrong" #223

Closed KSatC5 closed 3 months ago

KSatC5 commented 3 months ago

Hi, I don't think this is a bug, more like something I'm doing wrong, but there's no category for that.

I am trying to use this tool (which is awesome by the way) to troubleshoot an issue I'm having with the most recent version of XO. I am trying to install an old commit of XO, which according to the xo-install.cfg is supported. However, I've tried putting in the short 7-character commit code as so:

BRANCH="6056a61"

and even tried the full commit string:

BRANCH="6056a618c3e503fcc0de4fe19007574e40bfddd5"

Both to no avail, I receive "something went wrong" multiple times. I assume I am not formatting it correctly. Any guidance would be appreciated!

Thanks.

LPJon commented 3 months ago

@KSatC5 You can't update to a commit directly. You have to clone the "Branch"....in this case would be "master" and then reset your local clone to a commit using git reset --hard <commit>. This will let you compile the up to that commit. Here is a link to a youtube video describing how to do it. However, this feature is not setup in this script so you will need technical knowledge of how to do this or @ronivay will need to add it. I may be able to provide you an edited version here in a while that will make this work....no promises though....and it would be untested.

ronivay commented 3 months ago

Hi,

Yes, providing a commit (short or long hash) in the branch setting is supported. Please check the logs what actually goes wrong so i can possibly assist with this issue.

LPJon commented 3 months ago

@ronivay Hey, sorry I didn't mean to walk on toes. I have not seen the branch method used that way before, so I assumed it was just for specifying a full branch only. Either way I already made a quick and dirty edit that I think would also work and not interfere too much with your code. Feel free to keep it if it works and you want it. Also, since a commit made 2 days ago the proxy does not fully work anymore. So far my testing shows everything after commit 0ccfd4b makes viewing VM consoles through the proxy dead in the water. I'm not sure if it's affected anthing else yet. There is also a new edit to appliance.mjs that probably interfears with your patch.

@KSatC5 In the meantime if you want to try a solution that has been working for me for some time you can give this a shot. No promises though....and remember it's untested in this script. Just be sure to edit the XOACECOMMIT variable at the top of the script or you will get the latest the script offers. Long or short commit hash should be supported.

#!/bin/bash
# shellcheck disable=SC2155,SC2207,SC2015

#########################################################################
# Title: XenOrchestraInstallerUpdater                                   #
# Author: Roni Väyrynen                                                 #
# Repository: https://github.com/ronivay/XenOrchestraInstallerUpdater   #
#########################################################################

# Specify a specific commit to use here. (An empty value will use the latest commit)
XOACECOMMIT=""

SCRIPT_DIR="$(dirname "$0")"
SAMPLE_CONFIG_FILE="$SCRIPT_DIR/sample.xo-install.cfg"
CONFIG_FILE="$SCRIPT_DIR/xo-install.cfg"

# Deploy default configuration file if the user doesn't have their own yet.
if [[ ! -s "$CONFIG_FILE" ]]; then
    cp "$SAMPLE_CONFIG_FILE" "$CONFIG_FILE"
fi

# See this file for all script configuration variables.
# shellcheck disable=SC1090
source "$CONFIG_FILE"

# Set some default variables if sourcing config file fails for some reason
SELFUPGRADE=${SELFUPGRADE:-"true"}
PORT=${PORT:-80}
INSTALLDIR=${INSTALLDIR:-"/opt/xo"}
BRANCH=${BRANCH:-"master"}
LOGPATH=${LOGPATH:-$(dirname "$(realpath "$0")")/logs}
AUTOUPDATE=${AUTOUPDATE:-"true"}
PRESERVE=${PRESERVE:-"3"}
XOUSER=${XOUSER:-"root"}
CONFIGPATH=$(getent passwd "$XOUSER" | cut -d: -f6)
CONFIGPATH_PROXY=$(getent passwd root | cut -d: -f6)
CONFIGUPDATE=${CONFIGUPDATE:-"true"}
PLUGINS="${PLUGINS:-"all"}"
ADDITIONAL_PLUGINS="${ADDITIONAL_PLUGINS:-"none"}"
REPOSITORY="${REPOSITORY:-"https://github.com/vatesfr/xen-orchestra"}"
OS_CHECK="${OS_CHECK:-"true"}"
ARCH_CHECK="${ARCH_CHECK:-"true"}"
PATH_TO_HTTPS_CERT="${PATH_TO_HTTPS_CERT:-""}"
PATH_TO_HTTPS_KEY="${PATH_TO_HTTPS_KEY:-""}"
PATH_TO_HOST_CA="${PATH_TO_HOST_CA:-""}"
AUTOCERT="${AUTOCERT:-"false"}"
ACME="${ACME:-"false"}"
ACME_EMAIL="${ACME_EMAIL:-""}"
ACME_CA="${ACME_CA:-"letsencrypt/production"}"
USESUDO="${USESUDO:-"false"}"
GENSUDO="${GENSUDO:-"false"}"
INSTALL_REPOS="${INSTALL_REPOS:-"true"}"
SYSLOG_TARGET="${SYSLOG_TARGET:-""}"
YARN_CACHE_CLEANUP="${YARN_CACHE_CLEANUP:-"false"}"
YARN_NETWORK_TIMEOUT="${YARN_NETWORK_TIMEOUT:-"300000"}"

# set variables not changeable in configfile
TIME=$(date +%Y%m%d%H%M)
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
LOGFILE="${LOGPATH}/xo-install.log-$TIME"
NODEVERSION="18"
FORCE="false"
INTERACTIVE="false"
SUDOERSFILE="/etc/sudoers.d/xo-server-$XOUSER"

# Set path where new source is cloned/pulled
XO_SRC_DIR="$INSTALLDIR/xo-src/xen-orchestra"

# Set variables for stdout print
COLOR_N='\e[0m'
COLOR_GREEN='\e[1;32m'
COLOR_RED='\e[1;31m'
COLOR_BLUE='\e[1;34m'
COLOR_WHITE='\e[1;97m'
OK="[${COLOR_GREEN}ok${COLOR_N}]"
FAIL="[${COLOR_RED}fail${COLOR_N}]"
INFO="[${COLOR_BLUE}info${COLOR_N}]"
PROGRESS="[${COLOR_BLUE}..${COLOR_N}]"

# create logpath if doesn't exist
if [[ ! -d "$LOGPATH" ]]; then
    mkdir -p "$LOGPATH"
fi

function CheckUser {

    # Make sure the script is ran as root

    if [[ ! $(runcmd_stdout "id -u") == "0" ]]; then
        printfail "This script needs to be ran as root"
        exit 1
    fi

}

# script self upgrade
function SelfUpgrade {

    set -o pipefail

    if [[ "$SELFUPGRADE" != "true" ]]; then
        return 0
    fi

    if [[ -d "$SCRIPT_DIR/.git" ]] && [[ -n $(runcmd_stdout "command -v git") ]]; then
        local REMOTE="$(runcmd_stdout "cd $SCRIPT_DIR && git config --get remote.origin.url")"
        if [[ "$REMOTE" == *"ronivay/XenOrchestraInstallerUpdater"* ]]; then
            if [[ -n $(runcmd_stdout "cd $SCRIPT_DIR && git status --porcelain") ]]; then
                printfail "Local changes in this script directory. Not attempting to self upgrade"
                return 0
            fi
            runcmd "cd $SCRIPT_DIR && git fetch"
            local OLD_SCRIPT_VERSION="$(runcmd_stdout "cd $SCRIPT_DIR && git rev-parse --short HEAD")"
            local NEW_SCRIPT_VERSION="$(runcmd_stdout "cd $SCRIPT_DIR && git rev-parse --short FETCH_HEAD")"
            if [[ $(runcmd_stdout "cd $SCRIPT_DIR && git diff --name-only @{upstream}| grep xo-install.sh") ]]; then
                printinfo "Newer version of script available, attempting to self upgrade from '$OLD_SCRIPT_VERSION' to '$NEW_SCRIPT_VERSION'"
                runcmd "cd $SCRIPT_DIR && git pull --ff-only" &&
                    {
                        printok "Self upgrade done"
                        exec "$SCRIPT_DIR/xo-install.sh" "$@"
                    } ||
                    printfail "Failed to self upgrade. Check $LOGFILE for more details. Continuing with current version"
            fi
        fi
    fi

}

# log script version (git commit) and configuration variables to logfile
function ScriptInfo {

    set -o pipefail

    local SCRIPTVERSION=$(cd "$SCRIPT_DIR" 2>/dev/null && git rev-parse --short HEAD 2>/dev/null)

    [ -z "$SCRIPTVERSION" ] && SCRIPTVERSION="undefined"
    echo "Running script version $SCRIPTVERSION with config:" >>"$LOGFILE"
    echo >>"$LOGFILE"
    [ -s "$CONFIG_FILE" ] && grep -Eo '^[A-Z_]+.*' "$CONFIG_FILE" >>"$LOGFILE" || echo "No config file found" >>"$LOGFILE"
    echo >>"$LOGFILE"
}

# log actual command and it's stderr/stdout to logfile in one go
function runcmd {

    echo "+ $1" >>"$LOGFILE"
    bash -c -o pipefail "$1" >>"$LOGFILE" 2>&1 || return 1
}

# log actual command and it's stderr to logfile in one go
function runcmd_stdout {

    echo "+ $1" >>"$LOGFILE"
    # shellcheck disable=SC2094
    bash -c -o pipefail "$1" 2>>"$LOGFILE" | tee -a "$LOGFILE" || return 1
}

# make output we print pretty
function printprog {
    echo -ne "${PROGRESS} $*"
}

function printok {
    # shellcheck disable=SC1117
    echo -e "\r${OK} $*"
}

function printfail {
    echo -e "${FAIL} $*"
}

function printinfo {
    echo -e "${INFO} $*"
}

# if script fails at a stage where installation is not complete, we don't want to keep the install specific directory and content
# this is called by trap inside different functions
function ErrorHandling {

    echo
    echo
    printfail "Something went wrong, exiting. Check $LOGFILE for more details and use rollback feature if needed"

    if [[ -d "$INSTALLDIR/xo-builds/xen-orchestra-$TIME" ]]; then
        echo
        printfail "Removing $INSTALLDIR/xo-builds/xen-orchestra-$TIME because of failed installation."
        runcmd "rm -rf $INSTALLDIR/xo-builds/xen-orchestra-$TIME"
        echo
    fi

    exit 1
}

# install package dependencies to rpm distros, based on: https://xen-orchestra.com/docs/from_the_sources.html
function InstallDependenciesRPM {

    set -euo pipefail

    trap ErrorHandling ERR INT

    # Install necessary dependencies for XO build

    # only install epel-release if doesn't exist and user allows it to be installed
    if [[ -z $(runcmd_stdout "rpm -qa epel-release") ]] && [[ "$INSTALL_REPOS" == "true" ]]; then
        echo
        printprog "Installing epel-repo"
        runcmd "yum -y install epel-release"
        printok "Installing epel-repo"
    fi

    # install packages
    echo
    printprog "Installing build dependencies, redis server, python3, git, nfs-utils, cifs-utils, lvm2, ntfs-3g, dmidecode"
    runcmd "yum -y install gcc gcc-c++ make openssl-devel redis libpng-devel python3 git nfs-utils cifs-utils lvm2 ntfs-3g dmidecode"
    printok "Installing build dependencies, redis server, python3, git, nfs-utils, cifs-utils, lvm2, ntfs-3g, dmidecode"

    # only run automated node install if executable not found
    if [[ -z $(runcmd_stdout "command -v node") ]]; then
        echo
        printprog "Installing node.js"

        # only install nodejs repo if user allows it to be installed
        if [[ "$INSTALL_REPOS" == "true" ]]; then
            runcmd "curl -s -L https://rpm.nodesource.com/setup_${NODEVERSION}.x | bash -"
        fi

        runcmd "yum install -y nodejs"
        printok "Installing node.js"
    else
        UpdateNodeYarn
    fi

    # only install yarn repo and package if not found
    if [[ -z $(runcmd_stdout "command -v yarn") ]]; then
        echo
        printprog "Installing yarn"

        # only install yarn repo if user allows it to be installed
        if [[ "$INSTALL_REPOS" == "true" ]]; then
            runcmd "curl -s -o /etc/yum.repos.d/yarn.repo https://dl.yarnpkg.com/rpm/yarn.repo"
        fi

        runcmd "yum -y install yarn"
        printok "Installing yarn"
    fi

    # only install libvhdi-tools if vhdimount is not present
    if [[ -z $(runcmd_stdout "command -v vhdimount") ]]; then
        echo
        printprog "Installing libvhdi-tools"
        if [[ "$INSTALL_REPOS" == "true" ]]; then
            runcmd "rpm -ivh https://forensics.cert.org/cert-forensics-tools-release-el${OSVERSION}.rpm"
            runcmd "sed -i 's/enabled=1/enabled=0/g' /etc/yum.repos.d/cert-forensics-tools.repo"
            runcmd "yum --enablerepo=forensics install -y libvhdi-tools"
        else
            runcmd "yum install -y libvhdi-tools"
        fi
        printok "Installing libvhdi-tools"
    fi

    echo
    printprog "Enabling and starting redis service"
    runcmd "/bin/systemctl enable redis && /bin/systemctl start redis"
    printok "Enabling and starting redis service"

    echo
    printprog "Enabling and starting rpcbind service"
    runcmd "/bin/systemctl enable rpcbind && /bin/systemctl start rpcbind"
    printok "Enabling and starting rpcbind service"

}

# install package dependencies to deb distros, based on: https://xen-orchestra.com/docs/from_the_sources.html
function InstallDependenciesDeb {

    set -euo pipefail

    trap ErrorHandling ERR INT

    # Install necessary dependencies for XO build

    if [[ "$OSNAME" == "Ubuntu" ]] && [[ "$INSTALL_REPOS" == "true" ]]; then
        echo
        printprog "OS Ubuntu so making sure universe repository is enabled"
        runcmd "apt-get install -y software-properties-common"
        runcmd "add-apt-repository -y universe"
        printok "OS Ubuntu so making sure universe repository is enabled"
    fi

    echo
    printprog "Running apt-get update"
    runcmd "apt-get update"
    printok "Running apt-get update"

    # install packages
    echo
    printprog "Installing build dependencies, redis server, python3-minimal, git, libvhdi-utils, lvm2, nfs-common, cifs-utils, curl, ntfs-3g, dmidecode"
    runcmd "apt-get install -y build-essential redis-server libpng-dev git libvhdi-utils python3-minimal lvm2 nfs-common cifs-utils curl ntfs-3g dmidecode"
    printok "Installing build dependencies, redis server, python3-minimal, git, libvhdi-utils, lvm2, nfs-common, cifs-utils, curl, ntfs-3g, dmidecode"

    # Install apt-transport-https and ca-certificates because of yarn https repo url
    echo
    printprog "Installing apt-transport-https and ca-certificates packages to support https repos"
    runcmd "apt-get install -y apt-transport-https ca-certificates"
    printok "Installing apt-transport-https and ca-certificates packages to support https repos"

    if [[ "$OSNAME" == "Debian" ]] && [[ "$OSVERSION" =~ ^(10|11|12)$ ]]; then
        echo
        printprog "Debian 10/11/12, so installing gnupg also"
        runcmd "apt-get install gnupg -y"
        printok "Debian 10/11/12, so installing gnupg also"
    fi

    # install setcap for non-root port binding if missing
    if [[ -z $(runcmd_stdout "command -v setcap") ]]; then
        echo
        printprog "Installing setcap"
        runcmd "apt-get install -y libcap2-bin"
        printok "Installing setcap"
    fi

    # only run automated node install if executable not found
    if [[ -z $(runcmd_stdout "command -v node") ]] || [[ -z $(runcmd_stdout "command -v npm") ]]; then
        echo
        printprog "Installing node.js"

        # only install nodejs repo if user allows it to be installed
        if [[ "$INSTALL_REPOS" == "true" ]]; then
            runcmd "curl -sL https://deb.nodesource.com/setup_${NODEVERSION}.x | bash -"
        fi

        runcmd "apt-get install -y nodejs"
        printok "Installing node.js"
    else
        UpdateNodeYarn
    fi

    # only install yarn repo and package if not found
    if [[ -z $(runcmd_stdout "command -v yarn") ]]; then
        echo
        printprog "Installing yarn"

        # only install yarn repo if user allows it to be installed
        if [[ "$INSTALL_REPOS" == "true" ]]; then
            runcmd "curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -"
            runcmd "echo \"deb https://dl.yarnpkg.com/debian/ stable main\" | tee /etc/apt/sources.list.d/yarn.list"
        fi

        runcmd "apt-get update"
        runcmd "apt-get install -y yarn"
        printok "Installing yarn"
    fi

    echo
    printprog "Enabling and starting redis service"
    runcmd "/bin/systemctl enable redis-server && /bin/systemctl start redis-server"
    printok "Enabling and starting redis service"

    echo
    printprog "Enabling and starting rpcbind service"
    runcmd "/bin/systemctl enable rpcbind && /bin/systemctl start rpcbind"
    printok "Enabling and starting rpcbind service"

}

# keep node.js and yarn up to date
function UpdateNodeYarn {

    set -euo pipefail

    trap ErrorHandling ERR INT

    # user has an option to disable this behaviour in xo-install.cfg
    if [[ "$AUTOUPDATE" != "true" ]]; then
        return 0
    fi

    echo
    printinfo "Checking current node.js version"
    local NODEV=$(runcmd_stdout "node -v 2>/dev/null| grep -Eo '[0-9.]+' | cut -d'.' -f1")

    if [ "$PKG_FORMAT" == "rpm" ]; then
        # update node version if needed.
        # skip update if repository install is disabled as we can't quarantee this actually updates anything
        if [[ "${NODEV:-0}" -lt "${NODEVERSION}" ]] && [[ "$INSTALL_REPOS" == "true" ]]; then
            echo
            printprog "node.js version is ${NODEV:-"not installed"}, upgrading to ${NODEVERSION}.x"

            runcmd "curl -sL https://rpm.nodesource.com/setup_${NODEVERSION}.x | bash -"

            runcmd "yum clean all"
            runcmd "yum install -y nodejs"
            printok "node.js version is ${NODEV:-"not installed"}, upgrading to ${NODEVERSION}.x"
        else
            if [[ -z "$NODEV" ]]; then
                echo
                printfail "node.js not installed and INSTALL_REPOS set to false, can't continue"
                exit 1
            fi

            if [[ "$TASK" == "Update" ]]; then
                echo
                printprog "node.js version already on $NODEV, checking updates"
                runcmd "yum update -y nodejs yarn"
                printok "node.js version already on $NODEV, checking updates"
            elif [[ "$TASK" == "Installation" ]]; then
                echo
                printinfo "node.js version already on $NODEV"
            fi
        fi
    fi

    if [ "$PKG_FORMAT" == "deb" ]; then
        if [[ "${NODEV:-0}" -lt "${NODEVERSION}" ]] && [[ "$INSTALL_REPOS" == "true" ]]; then
            echo
            printprog "node.js version is ${NODEV:-"not installed"}, upgrading to ${NODEVERSION}.x"

            runcmd "curl -sL https://deb.nodesource.com/setup_${NODEVERSION}.x | bash -"

            runcmd "apt-get install -y nodejs"
            printok "node.js version is ${NODEV:-"not installed"}, upgrading to ${NODEVERSION}.x"
        else
            if [[ -z "$NODEV" ]]; then
                echo
                printfail "node.js not installed and INSTALL_REPOS set to false, can't continue"
                exit 1
            fi
            if [[ "$TASK" == "Update" ]]; then
                echo
                printprog "node.js version already on $NODEV, checking updates"
                runcmd "apt-get update"
                runcmd "apt-get install -y --only-upgrade nodejs yarn"
                printok "node.js version already on $NODEV, checking updates"
            elif [[ "$TASK" == "Installation" ]]; then
                echo
                printinfo "node.js version already on $NODEV"
            fi
        fi
    fi
}

# get source code for 3rd party plugins if any configured in xo-install.cfg
function InstallAdditionalXOPlugins {

    set -euo pipefail

    trap ErrorHandling ERR INT

    if [[ -z "$ADDITIONAL_PLUGINS" ]] || [[ "$ADDITIONAL_PLUGINS" == "none" ]]; then
        echo
        printinfo "No 3rd party plugins to install"
        return 0
    fi

    echo
    printprog "Fetching 3rd party plugin(s) source code"

    # shellcheck disable=SC1117
    local ADDITIONAL_PLUGIN_REGEX="^https?:\/\/.*.git$"
    local ADDITIONAL_PLUGIN
    IFS=',' read -ra ADDITIONAL_PLUGIN <<<"$ADDITIONAL_PLUGINS"
    for x in "${ADDITIONAL_PLUGIN[@]}"; do
        if ! [[ $x =~ $ADDITIONAL_PLUGIN_REGEX ]]; then
            echo
            printfail "$x format is not correct for 3rd party plugin, skipping.."
            continue
        fi
        local PLUGIN_NAME=$(runcmd_stdout "basename '$x' | rev | cut -c 5- | rev")
        local PLUGIN_SRC_DIR=$(runcmd_stdout "realpath -m '$XO_SRC_DIR/../$PLUGIN_NAME'")

        if [[ ! -d "$PLUGIN_SRC_DIR" ]]; then
            runcmd "mkdir -p \"$PLUGIN_SRC_DIR\""
            runcmd "git clone \"${x}\" \"$PLUGIN_SRC_DIR\""
        else
            runcmd "cd \"$PLUGIN_SRC_DIR\" && git pull --ff-only"
            runcmd "cd $SCRIPT_DIR"
        fi

        runcmd "cp -r $PLUGIN_SRC_DIR $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/"
    done

    printok "Fetching 3rd party plugin(s) source code"
}

# symlink plugins in place based on what is set in xo-install.cfg
function InstallXOPlugins {

    set -euo pipefail

    trap ErrorHandling ERR INT

    if [[ -z "$PLUGINS" ]] || [[ "$PLUGINS" == "none" ]]; then
        echo
        printinfo "No plugins to install"
        return 0
    fi

    echo
    printprog "Installing plugins"

    if [[ "$PLUGINS" == "all" ]]; then
        # shellcheck disable=SC1117
        runcmd "find \"$INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/\" -maxdepth 1 -mindepth 1 -not -name \"xo-server\" -not -name \"xo-web\" -not -name \"xo-server-cloud\" -not -name \"xo-server-test*\" -exec ln -sn {} \"$INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/node_modules/\" \;"
    else
        local PLUGIN
        IFS=',' read -ra PLUGIN <<<"$PLUGINS"
        for x in "${PLUGIN[@]}"; do
            if [[ $(runcmd_stdout "find $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages -type d -name '$x'") ]]; then
                runcmd "ln -sn $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/$x $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/node_modules/"
            fi
        done
    fi

    printok "Installing plugins"

}

# install sudo package and generate config if defined in configuration
function InstallSudo {

    set -euo pipefail

    trap ErrorHandling ERR INT

    if [[ -z $(runcmd_stdout "command -v sudo") ]]; then
        if [[ "$PKG_FORMAT" == "deb" ]]; then
            echo
            printprog "Installing sudo"
            runcmd "apt-get install -y sudo"
            printok "Installing sudo"
        elif [[ "$PKG_FORMAT" == "rpm" ]]; then
            printprog "Installing sudo"
            runcmd "yum install -y sudo"
            printok "Installing sudo"
        fi
    fi

    if [[ "$GENSUDO" == "true" ]] && [[ ! -f "$SUDOERSFILE" ]]; then
        echo
        printinfo "Generating sudoers configuration to $SUDOERSFILE"
        TMPSUDOERS="$(mktemp /tmp/xo-sudoers.XXXXXX)"
        runcmd "echo '$XOUSER ALL=(root) NOPASSWD: /bin/mount, /bin/umount, /bin/findmnt' > '$TMPSUDOERS'"
        if runcmd "visudo -cf $TMPSUDOERS"; then
            runcmd "mv $TMPSUDOERS $SUDOERSFILE"
        else
            printfail "sudoers syntax check failed, not activating $SUDOERSFILE"
            runcmd "rm -f $TMPSUDOERS"
        fi
    fi

}

function PrepInstall {

    set -euo pipefail

    trap ErrorHandling ERR INT

    if [[ "$XO_SVC" == "xo-server" ]]; then
        local XO_SVC_DESC="Xen Orchestra"
    fi
    if [[ "$XO_SVC" == "xo-proxy" ]]; then
        local XO_SVC_DESC="Xen Orchestra Proxy"
    fi

    # Create installation directory if doesn't exist already
    if [[ ! -d "$INSTALLDIR" ]]; then
        echo
        printinfo "Creating missing basedir to $INSTALLDIR"
        runcmd "mkdir -p \"$INSTALLDIR\""
    fi

    # Create missing xo-builds directory if doesn't exist already
    if [[ ! -d "$INSTALLDIR/xo-builds" ]]; then
        echo
        printinfo "Creating missing xo-builds directory to $INSTALLDIR/xo-builds"
        runcmd "mkdir \"$INSTALLDIR/xo-builds\""
    fi

    echo
    # keep the actual source code in one directory and either clone or git fetch depending on if directory exists already
    printinfo "Fetching $XO_SVC_DESC source code"
    if [[ ! -d "$XO_SRC_DIR" ]]; then
        runcmd "mkdir -p \"$XO_SRC_DIR\""
        runcmd "git clone \"${REPOSITORY}\" \"$XO_SRC_DIR\""
    else
        runcmd "cd \"$XO_SRC_DIR\" && git remote set-url origin \"${REPOSITORY}\" && \
            git fetch --prune && \
            git reset --hard origin/master && \
            git clean -xdff"
    fi

    # Deploy the latest xen-orchestra source to the new install directory.
    echo
    printinfo "Creating install directory: $INSTALLDIR/xo-builds/xen-orchestra-$TIME"
    runcmd "rm -rf \"$INSTALLDIR/xo-builds/xen-orchestra-$TIME\""
    runcmd "cp -r \"$XO_SRC_DIR\" \"$INSTALLDIR/xo-builds/xen-orchestra-$TIME\""

    # checkout configured branch if not set as master
    if [[ "$BRANCH" != "master" ]]; then
        echo
        printinfo "Checking out source code from branch/commit '$BRANCH'"

        runcmd "cd $INSTALLDIR/xo-builds/xen-orchestra-$TIME && git checkout $BRANCH"
        runcmd "cd $SCRIPT_DIR"
    fi

    # Check if the new repo is any different from the currently-installed
    # one. If not, then skip the build and delete the repo we just cloned.

    # Get the commit ID of the to-be-installed xen-orchestra.
    local NEW_REPO_HASH=$(runcmd_stdout "cd $INSTALLDIR/xo-builds/xen-orchestra-$TIME && git rev-parse HEAD")
    local NEW_REPO_HASH_SHORT=$(runcmd_stdout "cd $INSTALLDIR/xo-builds/xen-orchestra-$TIME && git rev-parse --short HEAD")
    runcmd "cd $SCRIPT_DIR"

    # Get the commit ID of the currently-installed xen-orchestra (if one
    # exists).
    if [[ -L "$INSTALLDIR/$XO_SVC" ]] && [[ -n $(runcmd_stdout "readlink -e $INSTALLDIR/$XO_SVC") ]]; then
        local OLD_REPO_HASH=$(runcmd_stdout "cd $INSTALLDIR/$XO_SVC && git rev-parse HEAD")
        local OLD_REPO_HASH_SHORT=$(runcmd_stdout "cd $INSTALLDIR/$XO_SVC && git rev-parse --short HEAD")
        runcmd "cd $SCRIPT_DIR"
    else
        # If there's no existing installation, then we definitely want
        # to proceed with the bulid.
        local OLD_REPO_HASH=""
        local OLD_REPO_HASH_SHORT=""
    fi

    # If the new install is no different from the existing install, then don't
    # proceed with the build.
    if [[ "$NEW_REPO_HASH" == "$OLD_REPO_HASH" ]] && [[ "$FORCE" != "true" ]]; then
        echo
        # if any non interactive arguments used in script startup, we don't want to show any prompts
        if [[ "$INTERACTIVE" == "true" ]]; then
            printinfo "No changes to $XO_SVC_DESC since previous install. Run update anyway?"
            read -r -p "[y/N]: " answer
            case "$answer" in
                y)
                    :
                    ;;
                *)
                    printinfo "Cleaning up install directory: $INSTALLDIR/xo-builds/xen-orchestra-$TIME"
                    runcmd "rm -rf $INSTALLDIR/xo-builds/xen-orchestra-$TIME"
                    exit 0
                    ;;
            esac
        else
            printinfo "No changes to $XO_SVC_DESC since previous install. Skipping build. Use the --force to update anyway."
            printinfo "Cleaning up install directory: $INSTALLDIR/xo-builds/xen-orchestra-$TIME"
            runcmd "rm -rf $INSTALLDIR/xo-builds/xen-orchestra-$TIME"
            exit 0
        fi
    fi

    # If this isn't a fresh install, then list the upgrade the user is making.
    if [[ -n "$OLD_REPO_HASH" ]]; then
        echo
        if [[ "$FORCE" != "true" ]]; then
            printinfo "Updating $XO_SVC_DESC from '$OLD_REPO_HASH_SHORT' to '$NEW_REPO_HASH_SHORT'"
            echo "Updating $XO_SVC_DESC from '$OLD_REPO_HASH_SHORT' to '$NEW_REPO_HASH_SHORT'" >>"$LOGFILE"
        else
            printinfo "Updating $XO_SVC_DESC (forced) from '$OLD_REPO_HASH_SHORT' to '$NEW_REPO_HASH_SHORT'"
            echo "Updating $XO_SVC_DESC (forced) from '$OLD_REPO_HASH_SHORT' to '$NEW_REPO_HASH_SHORT'" >>"$LOGFILE"
        fi
    else
        echo
        printinfo "Installing $XO_SVC_DESC from branch: $BRANCH - commit: $NEW_REPO_HASH_SHORT"
        echo "Installing $XO_SVC_DESC from branch: $BRANCH - commit: $NEW_REPO_HASH_SHORT" >>"$LOGFILE"
        TASK="Installation"
    fi

}

# run actual xen orchestra installation. procedure is the same for new installation and update. we always build it from scratch.
function InstallXO {
    if [[ -n "$XOACECOMMIT" ]]; then
      echo "An XOACE Commit was specified....resetting to this commit now..."
      runcmd "cd $INSTALLDIR/xo-builds/xen-orchestra-$TIME && git reset --hard $XOACECOMMIT"
      echo "Done!"
    fi

    set -euo pipefail

    trap ErrorHandling ERR INT

    # Create user if doesn't exist (if defined)

    if [[ "$XOUSER" != "root" ]]; then
        if [[ -z $(runcmd_stdout "getent passwd $XOUSER") ]]; then
            echo
            printprog "Creating missing $XOUSER user"
            runcmd "useradd -s /sbin/nologin $XOUSER -m"
            printok "Creating missing $XOUSER user"
            CONFIGPATH=$(getent passwd "$XOUSER" | cut -d: -f6)
        fi
        if [[ "$USESUDO" == "true" ]]; then
            InstallSudo
        fi
    fi

    PrepInstall

    # Fetch 3rd party plugins source code
    InstallAdditionalXOPlugins

    echo
    printinfo "xo-server and xo-web build takes quite a while. Grab a cup of coffee and lay back"
    echo
    printprog "Running installation"
    runcmd "cd $INSTALLDIR/xo-builds/xen-orchestra-$TIME && yarn --network-timeout ${YARN_NETWORK_TIMEOUT} && yarn --network-timeout ${YARN_NETWORK_TIMEOUT} build"
    printok "Running installation"

    # Install plugins (takes care of 3rd party plugins as well)
    InstallXOPlugins

    # shutdown possibly running xo-server
    if [[ $(runcmd_stdout "pgrep -f xo-server") ]]; then
        echo
        printprog "Shutting down running xo-server"
        runcmd "/bin/systemctl stop xo-server" || {
            printfail "failed to stop service, exiting..."
            exit 1
        }
        printok "Shutting down running xo-server"
        sleep 3
    fi

    echo
    printinfo "Fixing binary path in systemd service configuration file"
    # shellcheck disable=SC1117
    runcmd "sed -i \"s#ExecStart=.*#ExecStart=$INSTALLDIR\/xo-server\/dist\/cli.mjs#\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/xo-server.service"
    printinfo "Adding WorkingDirectory parameter to systemd service configuration file"
    # shellcheck disable=SC1117
    runcmd "sed -i \"/ExecStart=.*/a WorkingDirectory=$INSTALLDIR/xo-server\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/xo-server.service"
    if [[ -n "$PATH_TO_HOST_CA" ]]; then
        printinfo "Adding custom CA environment variable to systemd service configuration file"
        runcmd "sed -i \"/Environment=.*/a Environment=NODE_EXTRA_CA_CERTS=$PATH_TO_HOST_CA\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/xo-server.service"
    fi

    # if service not running as root, we need to deal with the fact that port binding might not be allowed
    if [[ "$XOUSER" != "root" ]]; then
        printinfo "Adding user to systemd config"
        # shellcheck disable=SC1117
        runcmd "sed -i \"/SyslogIdentifier=.*/a User=$XOUSER\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/xo-server.service"

        if [ "$PORT" -le "1024" ]; then
            local NODEBINARY=$(runcmd_stdout "command -v node")
            if [[ -L "$NODEBINARY" ]]; then
                local NODEBINARY=$(runcmd_stdout "readlink -e $NODEBINARY")
            fi

            if [[ -n "$NODEBINARY" ]]; then
                printprog "Attempting to set cap_net_bind_service permission for $NODEBINARY"
                runcmd "setcap 'cap_net_bind_service=+ep' $NODEBINARY" && printok "Attempting to set cap_net_bind_service permission for $NODEBINARY" ||
                    {
                        printfail "Attempting to set cap_net_bind_service permission for $NODEBINARY"
                        echo "  Non-privileged user might not be able to bind to <1024 port. xo-server won't start most likely"
                    }
            else
                printfail "Can't find node executable, or it's a symlink to non existing file. Not trying to setcap. xo-server won't start most likely"
            fi
        fi
    fi

    # fix to prevent older installations to not update because systemd service is not symlinked anymore
    if [[ $(runcmd_stdout "find /etc/systemd/system -maxdepth 1 -type l -name 'xo-server.service'") ]]; then
        runcmd "rm -f /etc/systemd/system/xo-server.service"
    fi

    printinfo "Replacing systemd service configuration file"

    # always replace systemd service configuration if it changes in future updates
    runcmd "/bin/cp -f $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/xo-server.service /etc/systemd/system/xo-server.service"
    sleep 2
    printinfo "Reloading systemd configuration"
    runcmd "/bin/systemctl daemon-reload"
    sleep 2

    # if xen orchestra configuration file doesn't exist or configuration update is not disabled in xo-install.cfg, we create it
    if [[ ! -f "$CONFIGPATH/.config/xo-server/config.toml" ]] || [[ "$CONFIGUPDATE" == "true" ]]; then

        echo
        printinfo "Fixing relative path to xo-web installation in xo-server configuration file"
        # shellcheck disable=SC1117
        runcmd "sed -i \"s%#'/any/url' = '/path/to/directory'%'/' = '$INSTALLDIR/xo-web/dist/'%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
        printinfo "Changing redis connection address in xo-server configuration file"
        runcmd "sed -i \"s%#uri = 'redis://redis.company.lan/42'%uri = 'redis://127.0.0.1:6379/0'%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"

        if [[ "$PORT" != "80" ]]; then
            printinfo "Changing port in xo-server configuration file"
            # shellcheck disable=SC1117
            runcmd "sed -i \"s/port = 80/port = $PORT/\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
            sleep 2
        fi

        if [[ "$HTTPS" == "true" ]]; then
            printinfo "Enabling HTTPS in xo-server configuration file"
            # shellcheck disable=SC1117
            runcmd "sed -i \"s%# cert = '.\/certificate.pem'%cert = '$PATH_TO_HTTPS_CERT'%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
            # shellcheck disable=SC1117
            runcmd "sed -i \"s%# key = '.\/key.pem'%key = '$PATH_TO_HTTPS_KEY'%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
            if [[ "$AUTOCERT" == "true" ]]; then
                # shellcheck disable=SC1117
                runcmd "sed -i \"s%# autoCert = false%autoCert = true%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
            fi
            if [[ "$ACME" == "true" ]]; then
                runcmd "sed -i \"s%# \[\[http.listen\]\]%\[\[http.listen\]\]%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
                runcmd "sed -i \"s%# port = 443%port = 443%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
                runcmd "sed -i \"s%^# redirectToHttps = true%redirectToHttps = true%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
                runcmd "sed -i \"/^autoCert =.*/a acmeCa = '$ACME_CA'\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
                runcmd "sed -i \"/^autoCert = .*/a acmeDomain = '$ACME_DOMAIN'\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
                if [[ -n "$ACME_EMAIL" ]]; then
                    runcmd "sed -i \"/^autoCert =.*/a acmeEmail = '$ACME_EMAIL'\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
                fi
            fi
            sleep 2
        fi
        if [[ "$USESUDO" == "true" ]] && [[ "$XOUSER" != "root" ]]; then
            printinfo "Enabling useSudo in xo-server configuration file"
            runcmd "sed -i \"s/#useSudo = false/useSudo = true/\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
            printinfo "Changing default mountsDir in xo-server configuration file"
            runcmd "sed -i \"s%#mountsDir.*%mountsDir = '$INSTALLDIR/mounts'%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
            runcmd "mkdir -p $INSTALLDIR/mounts"
            runcmd "chown $XOUSER:$XOUSER $INSTALLDIR/mounts"
        fi

        if [[ -n "$SYSLOG_TARGET" ]]; then
            printinfo "Enabling remote syslog in xo-server configuration file"
            runcmd "sed -i \"s%#\[logs.transport.syslog\]%\[logs.transport.syslog\]%\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
            runcmd "sed -i \"/^\[logs.transport.syslog.*/a target = '$SYSLOG_TARGET'\" $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml"
        fi

        printinfo "Activating modified configuration file"
        runcmd "mkdir -p $CONFIGPATH/.config/xo-server"
        runcmd "mv -f $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server/sample.config.toml $CONFIGPATH/.config/xo-server/config.toml"

    fi

    echo
    # install/update is the same procedure so always symlink to most recent installation
    printinfo "Symlinking fresh xo-server install/update to $INSTALLDIR/xo-server"
    runcmd "ln -sfn $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-server $INSTALLDIR/xo-server"
    sleep 2
    printinfo "Symlinking fresh xo-web install/update to $INSTALLDIR/xo-web"
    runcmd "ln -sfn $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-web $INSTALLDIR/xo-web"
    sleep 2
    printinfo "Symlinking fresh xo-cli install/update to $INSTALLDIR/xo-cli"
    runcmd "ln -sfn $INSTALLDIR/xo-builds/xen-orchestra-$TIME/packages/xo-cli $INSTALLDIR/xo-cli"
    printinfo "Symlinking xo-cli script to /usr/local/bin/xo-cli"
    runcmd "ln -sfn $INSTALLDIR/xo-cli/index.mjs /usr/local/bin/xo-cli"

    # if not running as root, xen orchestra startup might not be able to create data directory so we create it here just in case
    if [[ "$XOUSER" != "root" ]]; then
        runcmd "chown -R $XOUSER:$XOUSER $INSTALLDIR/xo-builds/xen-orchestra-$TIME"

        if [ ! -d /var/lib/xo-server ]; then
            runcmd "mkdir /var/lib/xo-server"
        fi

        runcmd "chown -R $XOUSER:$XOUSER /var/lib/xo-server"

        runcmd "chown -R $XOUSER:$XOUSER $CONFIGPATH/.config/xo-server"

    fi

    echo
    printinfo "Starting xo-server..."
    runcmd "/bin/systemctl start xo-server"

    # no need to exit/trap on errors anymore
    set +eo pipefail
    trap - ERR INT

    VerifyServiceStart
}

function VerifyServiceStart {

    set -u

    if [[ "$XO_SVC" == "xo-proxy" ]]; then
        local PORT="443"
    fi

    PROXY_CONFIG_UPDATED=${PROXY_CONFIG_UPDATED:-"false"}

    # loop service logs for 60 seconds and look for line that indicates service was started. we only care about lines generated after script was started (LOGTIME)
    local count=0
    local limit=6
    # shellcheck disable=SC1117
    local servicestatus="$(runcmd_stdout "journalctl --since '$LOGTIME' -u $XO_SVC | grep 'Web server listening on https\{0,1\}:\/\/.*:$PORT'")"
    while [[ -z "$servicestatus" ]] && [[ "$count" -lt "$limit" ]]; do
        echo " waiting for port to be open"
        sleep 10
        # shellcheck disable=SC1117
        local servicestatus="$(runcmd_stdout "journalctl --since '$LOGTIME' -u $XO_SVC | grep 'Web server listening on https\{0,1\}:\/\/.*:$PORT'")"
        ((count++))
    done

    # if it looks like service started successfully based on logs..
    if [[ -n "$servicestatus" ]]; then
        echo
        if [[ "$XO_SVC" == "xo-server" ]]; then
            echo -e "       ${COLOR_GREEN}WebUI started in port $PORT. Make sure you have firewall rules in place to allow access.${COLOR_N}"
            # print username and password only when install was ran and skip while updating
            if [[ "$TASK" == "Installation" ]]; then
                echo -e "       ${COLOR_GREEN}Default username: admin@admin.net password: admin${COLOR_N}"
            fi
        fi
        if [[ "$XO_SVC" == "xo-proxy" ]]; then
            echo -e "       ${COLOR_GREEN}Proxy started in port $PORT. Make sure you have firewall rules in place to allow access from xen orchestra.${COLOR_N}"
            # print json config only if config file was generated
            if [[ "$PROXY_CONFIG_UPDATED" == "true" ]]; then
                echo -e "       ${COLOR_GREEN}Save following line as json file and use config import in Xen Orchestra to add proxy${COLOR_N}"
                echo
                echo "{\"proxies\":[{\"authenticationToken\":\"${PROXY_TOKEN}\",\"name\":\"${PROXY_NAME}\",\"vmUuid\":\"${PROXY_VM_UUID}\",\"id\":\"${PROXY_RANDOM_UUID}\"}]}"
            fi
        fi
        echo
        printinfo "$TASK successful. Enabling $XO_SVC service to start on reboot"
        echo "" >>"$LOGFILE"
        echo "$TASK succesful" >>"$LOGFILE"
        runcmd "/bin/systemctl enable $XO_SVC"
        echo
    # if service startup failed...
    else
        echo
        printfail "$TASK completed, but looks like there was a problem when starting $XO_SVC. Check $LOGFILE for more details"
        # shellcheck disable=SC2129
        echo "" >>"$LOGFILE"
        echo "$TASK failed" >>"$LOGFILE"
        echo "$XO_SVC service log:" >>"$LOGFILE"
        echo "" >>"$LOGFILE"
        runcmd "journalctl --since '$LOGTIME' -u $XO_SVC >> $LOGFILE"
        echo
        echo "Control $XO_SVC service with systemctl for stop/start/restart etc."
        exit 1
    fi

}

# run xen orchestra installation but also cleanup old installations based on value in xo-install.cfg
function UpdateXO {

    if [[ "$XO_SVC" == "xo-server" ]]; then
        InstallXO
    fi
    if [[ "$XO_SVC" == "xo-proxy" ]]; then
        InstallXOProxy
    fi

    set -uo pipefail

    if [[ "$PRESERVE" == "0" ]]; then
        printinfo "PRESERVE variable is set to 0. This needs to be at least 1. Not doing a cleanup"
        return 0
    fi

    # remove old builds. leave as many as defined in PRESERVE variable
    printprog "Removing old inactive installations after update. Leaving $PRESERVE latest"
    local INSTALLATIONS="$(runcmd_stdout "find $INSTALLDIR/xo-builds/ -maxdepth 1 -type d -name \"xen-orchestra*\" -printf \"%T@ %p\\n\" | sort -n | cut -d' ' -f2- | head -n -$PRESERVE")"
    local XO_SERVER_ACTIVE="$(runcmd_stdout "readlink -e $INSTALLDIR/xo-server")"
    local XO_WEB_ACTIVE="$(runcmd_stdout "readlink -e $INSTALLDIR/xo-web")"
    local XO_PROXY_ACTIVE="$(runcmd_stdout "readlink -e $INSTALLDIR/xo-proxy")"

    for DELETABLE in $INSTALLATIONS; do
        if [[ "$XO_SERVER_ACTIVE" != "${DELETABLE}"* ]] && [[ "$XO_WEB_ACTIVE" != "${DELETABLE}"* ]] && [[ "$XO_PROXY_ACTIVE" != "${DELETABLE}"* ]]; then
            runcmd "rm -rf $DELETABLE"
        fi
    done
    printok "Removing old inactive installations after update. Leaving $PRESERVE latest"
    echo

    # clear yarn cache if defined in configuration
    if [[ "$YARN_CACHE_CLEANUP" == "true" ]]; then
        printprog "Cleaning yarn cache"
        runcmd "yarn cache clean"
        printok "Cleaning yarn cache"
        echo
    fi
}

function InstallXOProxy {

    set -euo pipefail

    PrepInstall

    echo
    printinfo "xo-proxy build takes quite a while. Grab a cup of coffee and lay back"
    echo
    printprog "Running installation"
    runcmd "cd $INSTALLDIR/xo-builds/xen-orchestra-$TIME && yarn --network-timeout ${YARN_NETWORK_TIMEOUT} && yarn --network-timeout ${YARN_NETWORK_TIMEOUT} build"
    printok "Running installation"

    # shutdown possibly running xo-server
    if [[ $(runcmd_stdout "pgrep -f xo-proxy") ]]; then
        echo
        printprog "Shutting down running xo-proxy"
        runcmd "/bin/systemctl stop xo-proxy" || {
            printfail "failed to stop service, exiting..."
            exit 1
        }
        printok "Shutting down running xo-proxy"
        sleep 3
    fi

    echo
    printinfo "Disabling license check in proxy to enable running it in XO from sources"

    cat <<-EOF | runcmd "patch --fuzz=0 --no-backup-if-mismatch $INSTALLDIR/xo-builds/xen-orchestra-$TIME/@xen-orchestra/proxy/app/mixins/appliance.mjs"
--- appliance.mjs~  2022-03-30 15:28:52.360814994 +0300
+++ appliance.mjs   2022-03-30 15:27:57.823598169 +0300
@@ -153,10 +153,13 @@

   // A proxy can be bound to a unique license
   getSelfLicense() {
-    return Disposable.use(getUpdater(), async updater => {
-      const licenses = await updater.call('getSelfLicenses')
-      const now = Date.now()
-      return licenses.find(({ expires }) => expires === undefined || expires > now)
-    })
+  // modified by XenOrchestraInstallerUpdater
+  //
+  //  return Disposable.use(getUpdater(), async updater => {
+  //    const licenses = await updater.call('getSelfLicenses')
+  //    const now = Date.now()
+  //    return licenses.find(({ expires }) => expires === undefined || expires > now)
+  //  })
+    return true
   }
 }
EOF

    echo
    printinfo "Generate systemd service configuration file"

    cat <<EOF >/etc/systemd/system/xo-proxy.service
[Unit]
Description=xo-proxy
After=network-online.target

[Service]
ExecStart=$INSTALLDIR/xo-proxy/index.mjs
Restart=always
SyslogIdentifier=xo-proxy

[Install]
WantedBy=multi-user.target
EOF

    printinfo "Reloading systemd configuration"
    runcmd "/bin/systemctl daemon-reload"

    # if xen orchestra proxy configuration file doesn't exist or configuration update is not disabled in xo-install.cfg, we create it

    if [[ ! -f "$CONFIGPATH_PROXY/.config/xo-proxy/config.toml" ]]; then
        PROXY_VM_UUID="$(dmidecode -t system | grep UUID | awk '{print $NF}')"
        PROXY_RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
        PROXY_TOKEN="$(head -n50 /dev/urandom | tr -dc A-Z-a-z0-9_- | head -c 43)"
        PROXY_NAME="xo-ce-proxy-$TIME"
        PROXY_CONFIG_UPDATED="true"
        echo
        printinfo "No xo-proxy configuration present, copying default config to $CONFIGPATH_PROXY/.config/xo-proxy/config.toml"
        runcmd "mkdir -p $CONFIGPATH_PROXY/.config/xo-proxy"
        runcmd "cp $INSTALLDIR/xo-builds/xen-orchestra-$TIME/@xen-orchestra/proxy/config.toml $CONFIGPATH_PROXY/.config/xo-proxy/config.toml"

        printinfo "Adding authentication token to xo-proxy config"
        runcmd "sed -i \"s/^authenticationToken = .*/authenticationToken = '$PROXY_TOKEN'/\" $CONFIGPATH_PROXY/.config/xo-proxy/config.toml"
    fi

    echo
    printinfo "Symlinking fresh xo-proxy install/update to $INSTALLDIR/xo-proxy"
    runcmd "ln -sfn $INSTALLDIR/xo-builds/xen-orchestra-$TIME/@xen-orchestra/proxy $INSTALLDIR/xo-proxy"

    echo
    printinfo "Starting xo-proxy..."
    runcmd "/bin/systemctl start xo-proxy"

    # no need to exit/trap on errors anymore
    set +eo pipefail
    trap - ERR INT

    VerifyServiceStart
}

# if any arguments were given to script, handle them here
function HandleArgs {

    OPTS=$(getopt -o: --long force,rollback,update,install,proxy -- "$@")

    #shellcheck disable=SC2181
    if [[ $? != 0 ]]; then
        echo "Usage: $SCRIPT_DIR/$(basename "$0") [--install | --update | --rollback ] [--proxy] [--force]"
        exit 1
    fi

    eval set -- "$OPTS"

    local UPDATEARG=0
    local INSTALLARG=0
    local ROLLBACKARG=0
    local PROXYARG=0

    while true; do
        case "$1" in
            --force)
                shift
                FORCE="true"
                ;;
            --update)
                shift
                local UPDATEARG=1
                TASK="Update"
                ;;
            --install)
                shift
                local INSTALLARG=1
                TASK="Installation"
                ;;
            --rollback)
                shift
                local ROLLBACKARG=1
                ;;
            --proxy)
                shift
                local PROXYARG=1
                ;;
            --)
                shift
                break
                ;;
            *)
                shift
                break
                ;;
        esac
    done

    # can't run more than one task at the same time
    if [[ "$((INSTALLARG + UPDATEARG + ROLLBACKARG))" -gt 1 ]]; then
        echo "Define either install/update or rollback"
        exit 1
    fi

    if [[ "$UPDATEARG" -gt 0 ]]; then
        UpdateNodeYarn
        if [[ "$PROXYARG" -gt 0 ]]; then
            XO_SVC="xo-proxy"
            UpdateXO
        else
            XO_SVC="xo-server"
            UpdateXO
        fi
        exit
    fi

    if [[ "$INSTALLARG" -gt 0 ]]; then
        if [ "$PKG_FORMAT" == "rpm" ]; then
            InstallDependenciesRPM
        else
            InstallDependenciesDeb
        fi

        if [[ "$PROXYARG" -gt 0 ]]; then
            XO_SVC="xo-proxy"
            InstallXOProxy
        else
            XO_SVC="xo-server"
            InstallXO
        fi
        exit
    fi

    if [[ "$ROLLBACKARG" -gt 0 ]]; then
        RollBackInstallation
        exit
    fi

}

# all updates are individual complete installations so we have a possibility to rollback by just symlinking to different installation
function RollBackInstallation {

    set -uo pipefail

    local INSTALLATIONS=($(runcmd_stdout "find '$INSTALLDIR/xo-builds/' -maxdepth 1 -type d -name 'xen-orchestra-*'"))

    if [[ ${#INSTALLATIONS[@]} -le 1 ]]; then
        printinfo "One or less installations exist, nothing to change"
        exit 0
    fi

    if [[ -L "$INSTALLDIR/xo-proxy" ]] && [[ -n $(runcmd_stdout "readlink -e $INSTALLDIR/xo-proxy") ]]; then
        if [[ -L "$INSTALLDIR/xo-server" ]] && [[ -n $(runcmd_stdout "readlink -e $INSTALLDIR/xo-server") ]]; then
            echo "Looks like proxy AND xen orchestra are installed. Which one you want to rollback?"
            echo "1. Xen Orchestra"
            echo "2. Xen Orchestra Proxy"
            echo "3. Exit"
            read -r -p ": " answer
            case $answer in
                1)
                    XO_SVC="xo-server"
                    ;;
                2)
                    XO_SVC="xo-proxy"
                    ;;
                3)
                    exit
                    ;;
                *)
                    exit
                    ;;
            esac
        else
            XO_SVC="xo-proxy"
        fi
    else
        XO_SVC="xo-server"
    fi

    echo "Which installation to roll back?"
    echo
    local PS3="Pick a number. CTRL+C to exit: "
    local INSTALLATION
    select INSTALLATION in "${INSTALLATIONS[@]}"; do
        case $INSTALLATION in
            *xen-orchestra*)
                echo
                if [[ "$XO_SVC" == "xo-server" ]]; then
                    printinfo "Setting $INSTALLDIR/xo-server symlink to $INSTALLATION/packages/xo-server"
                    runcmd "ln -sfn $INSTALLATION/packages/xo-server $INSTALLDIR/xo-server"
                    printinfo "Setting $INSTALLDIR/xo-web symlink to $INSTALLATION/packages/xo-web"
                    runcmd "ln -sfn $INSTALLATION/packages/xo-web $INSTALLDIR/xo-web"
                    printinfo "Setting $INSTALLDIR/xo-cli symlink to $INSTALLATION/packages/xo-cli"
                    runcmd "ln -sfn $INSTALLATION/packages/xo-cli $INSTALLDIR/xo-cli"
                    echo
                    printinfo "Replacing xo.server.service systemd configuration file"
                    runcmd "/bin/cp -f $INSTALLATION/packages/xo-server/xo-server.service /etc/systemd/system/xo-server.service"
                    runcmd "/bin/systemctl daemon-reload"
                    echo
                    printinfo "Restarting xo-server..."
                    runcmd "/bin/systemctl restart xo-server"
                    echo
                    break
                fi
                if [[ "$XO_SVC" == "xo-proxy" ]]; then
                    printinfo "Setting $INSTALLDIR/xo-proxy symlink to $INSTALLATION/@xen-orchestra/proxy"
                    runcmd "ln -sfn $INSTALLATION/@xen-orchestra/proxy $INSTALLDIR/xo-proxy"
                    echo
                    printinfo "Restating xo-proxy..."
                    runcmd "/bin/systemctl restart xo-proxy"
                    echo
                    break
                fi
                ;;
            *)
                printfail "Try again"
                ;;
        esac
    done

}

# only specific list of operating systems are supported. check operating system name/version here
function CheckOS {

    OSVERSION=$(runcmd_stdout "grep ^VERSION_ID /etc/os-release | cut -d'=' -f2 | grep -Eo '[0-9]{1,2}' | head -1")
    OSNAME=$(runcmd_stdout "grep ^NAME /etc/os-release | cut -d'=' -f2 | sed 's/\"//g' | awk '{print \$1}'")

    # check that were not on official XOA VM. if yes, bail out
    if [[ $(runcmd_stdout "grep ^GRUB_DISTRIBUTOR /etc/default/grub | grep 'Xen Orchestra'") ]]; then
        printfail "Looks like this is the official XOA VM. Installation not supported, exiting"
        exit 1
    fi

    if [[ $(runcmd_stdout "command -v yum") ]]; then
        PKG_FORMAT="rpm"
    fi

    if [[ $(runcmd_stdout "command -v apt-get") ]]; then
        PKG_FORMAT="deb"
    fi

    # hard dependency which we can't skip so bail out if no yum/apt-get present
    if [[ -z "$PKG_FORMAT" ]]; then
        printfail "this script requires either yum or apt-get"
        exit 1
    fi

    # OS check can be skipped in xo-install.cfg for experimental purposes, skip the rest of this function if set to false
    if [[ "$OS_CHECK" != "true" ]]; then
        return 0
    fi

    if [[ ! "$OSNAME" =~ ^(Debian|Ubuntu|CentOS|Rocky|AlmaLinux)$ ]]; then
        printfail "Only Ubuntu/Debian/CentOS/Rocky/AlmaLinux supported"
        exit 1
    fi

    if [[ "$OSNAME" == "CentOS" ]] && [[ ! "$OSVERSION" =~ ^(8|9)$ ]]; then
        printfail "Only CentOS 8/9 supported"
        exit 1
    fi

    if [[ "$OSNAME" == "Rocky" ]] && [[ ! "$OSVERSION" =~ ^(8|9)$ ]]; then
        printfail "Only Rocky Linux 8/9 supported"
        exit 1
    fi

    if [[ "$OSNAME" == "AlmaLinux" ]] && [[ ! "$OSVERSION" =~ ^(8|9)$ ]]; then
        printfail "Only AlmaLinux 8/9 supported"
        exit 1
    fi

    if [[ "$OSNAME" == "Debian" ]] && [[ ! "$OSVERSION" =~ ^(10|11|12)$ ]]; then
        printfail "Only Debian 10/11/12 supported"
        exit 1
    fi

    if [[ "$OSNAME" == "Ubuntu" ]] && [[ ! "$OSVERSION" =~ ^(20|22)$ ]]; then
        printfail "Only Ubuntu 20/22 supported"
        exit 1
    fi

}

# we don't want anyone to attempt running this on xcp-ng/xenserver host, bail out if xe command is present
function CheckXE {

    if [[ $(runcmd_stdout "command -v xe") ]]; then
        printfail "xe binary found, don't try to run install on xcp-ng/xenserver host. use xo-vm-import.sh instead"
        exit 1
    fi
}

# x86_64 is defined as one of the requirements in xen orchestra documentation so we want to check that's the case
# https://xen-orchestra.com/docs/from_the_sources.html
function CheckArch {

    # can be disabled in xo-install.cfg for experimental purposes
    if [[ "$ARCH_CHECK" != "true" ]]; then
        return 0
    fi

    if [[ $(runcmd_stdout "uname -m") != "x86_64" ]]; then
        printfail "Installation supports only x86_64. You seem to be running architecture: $(uname -m)"
        exit 1
    fi
}

# script does alot of systemd related stuff so it's a hard requirement. bail out if not present
function CheckSystemd {

    if [[ -z $(runcmd_stdout "command -v systemctl") ]]; then
        printfail "This tool is designed to work with systemd enabled systems only"
        exit 1
    fi
}

# do not let the user define non functional cert/key pair
function CheckCertificate {
    if [[ "$HTTPS" == "true" ]]; then
        # if defined cert/key files don't exist and autocert is set to true, skip verification. Otherwise bail out.
        if [[ ! -f "$PATH_TO_HTTPS_CERT" ]] && [[ ! -f "$PATH_TO_HTTPS_KEY" ]]; then
            if [[ "$AUTOCERT" == "true" ]]; then
                return 0
            else
                printfail "Configured certificate: $PATH_TO_HTTPS_CERT and key: $PATH_TO_HTTPS_KEY missing. Check files and try again"
                exit 1
            fi
        fi
        # if defined cert/key files exist. check that they're compatible with each other.
        local CERT="$(runcmd_stdout "openssl x509 -pubkey -noout -in $PATH_TO_HTTPS_CERT | openssl md5")"
        local KEY="$(runcmd_stdout "openssl pkey -pubout -in $PATH_TO_HTTPS_KEY -outform PEM | openssl md5")"
        if [[ "$CERT" != "$KEY" ]]; then
            echo
            printinfo "$PATH_TO_HTTPS_CERT:"
            printinfo "$CERT"
            printinfo "$PATH_TO_HTTPS_KEY:"
            printinfo "$KEY"
            echo
            printfail "MD5 of your TLS key and certificate dont match. Please check files and try again."
            exit 1
        fi
    fi

}

# building xen orchestra from source is quite memory heavy and there has been cases with OOM when running with less than 3GB of memory. warn if running less
function CheckMemory {
    local SYSMEM=$(runcmd_stdout "grep MemTotal /proc/meminfo | awk '{print \$2}'")

    if [[ "$SYSMEM" -lt 3000000 ]]; then
        echo -e "${COLOR_RED}WARNING: you have less than 3GB of RAM in your system. Installation might run out of memory${COLOR_N}"
        # no prompt when running non interactive options
        if [[ "$INTERACTIVE" == "false" ]]; then
            return 0
        fi
        read -r -p "continue anyway? y/N: " answer
        case $answer in
            y)
                :
                ;;
            *)
                exit 0
                ;;
        esac
    fi

}

# we don't want to fill disk with new install/update so warn if there is too little disk space available
function CheckDiskFree {
    local FREEDISK=$(runcmd_stdout "df -P -k '${INSTALLDIR%/*}' | tail -1 | awk '{print \$4}'")

    if [[ "$FREEDISK" -lt 1048576 ]]; then
        echo -e "${COLOR_RED}WARNING: free disk space in ${INSTALLDIR%/*} seems to be less than 1GB. Install/update will most likely fail${COLOR_N}"
        # no prompt when running non interactive options
        if [[ "$INTERACTIVE" == "false" ]]; then
            return 0
        fi
        read -r -p "continue anyway? y/N: " answer
        case $answer in
            y)
                :
                ;;
            *)
                exit 0
                ;;
        esac
    fi
}

# interactive menu for different options
function StartUpScreen {

    echo "-----------------------------------------"
    echo
    echo "Welcome to automated Xen Orchestra install"
    echo
    echo "Following options will be used for installation:"
    echo
    echo -e "OS: ${COLOR_WHITE}$OSNAME $OSVERSION ${COLOR_N}"
    echo -e "Basedir: ${COLOR_WHITE}$INSTALLDIR ${COLOR_N}"
    echo -e "User: ${COLOR_WHITE}$XOUSER ${COLOR_N}"
    echo -e "Port: ${COLOR_WHITE}$PORT${COLOR_N}"
    echo -e "HTTPS: ${COLOR_WHITE}${HTTPS}${COLOR_N}"
    echo -e "Git Branch for source: ${COLOR_WHITE}$BRANCH${COLOR_N}"
    echo -e "Following plugins will be installed: ${COLOR_WHITE}$PLUGINS${COLOR_N}"
    echo -e "Number of previous installations to preserve: ${COLOR_WHITE}$PRESERVE${COLOR_N}"
    echo -e "Node.js and yarn auto update: ${COLOR_WHITE}$AUTOUPDATE${COLOR_N}"
    echo
    echo -e "Errorlog is stored to ${COLOR_WHITE}$LOGFILE${COLOR_N} for debug purposes"
    echo
    echo "Depending on which installation is chosen:"
    echo
    echo -e "Xen Orchestra configuration will be stored to ${COLOR_WHITE}$CONFIGPATH/.config/xo-server/config.toml${COLOR_N}, if you don't want it to be replaced with every update, set ${COLOR_WHITE}CONFIGUPDATE${COLOR_N} to false in ${COLOR_WHITE}xo-install.cfg${COLOR_N}"
    echo -e "Xen Orchestra Proxy configuration will be stored to ${COLOR_WHITE}$CONFIGPATH_PROXY/.config/xo-proxy/config.toml${COLOR_N}. Config won't be overwritten during update, ever"
    echo "-----------------------------------------"

    echo
    echo -e "${COLOR_WHITE}1. Install${COLOR_N}"
    echo -e "${COLOR_WHITE}2. Update${COLOR_N}"
    echo -e "${COLOR_WHITE}3. Rollback${COLOR_N}"
    echo -e "${COLOR_WHITE}4. Install proxy${COLOR_N}"
    echo -e "${COLOR_WHITE}5. Update proxy${COLOR_N}"
    echo -e "${COLOR_WHITE}6. Exit${COLOR_N}"
    echo
    read -r -p ": " option

    case $option in
        1)
            if [[ $(runcmd_stdout "pgrep -f xo-server") ]]; then
                echo "Looks like xo-server process is already running, consider running update instead. Continue anyway?"
                read -r -p "[y/N]: " answer
                case $answer in
                    y)
                        echo "Stopping xo-server..."
                        runcmd "/bin/systemctl stop xo-server" ||
                            {
                                printfail "failed to stop service, exiting..."
                                exit 1
                            }
                        ;;
                    n)
                        exit 0
                        ;;
                    *)
                        exit 0
                        ;;
                esac
            fi

            TASK="Installation"
            XO_SVC="xo-server"

            if [ "$PKG_FORMAT" == "rpm" ]; then
                InstallDependenciesRPM
                InstallXO
                exit 0
            fi
            if [ "$PKG_FORMAT" == "deb" ]; then
                InstallDependenciesDeb
                InstallXO
                exit 0
            fi
            ;;
        2)
            TASK="Update"
            XO_SVC="xo-server"
            UpdateNodeYarn
            UpdateXO
            exit 0
            ;;
        3)
            RollBackInstallation
            exit 0
            ;;
        4)
            if [[ $(runcmd_stdout "pgrep -f xo-proxy") ]]; then
                echo "Looks like xo-proxy process is already running, consider running update instead. Continue anyway?"
                read -r -p "[y/N]: " answer
                case $answer in
                    y)
                        echo "Stopping xo-proxy..."
                        runcmd "/bin/systemctl stop xo-proxy" ||
                            {
                                printfail "failed to stop service, exiting..."
                                exit 1
                            }
                        ;;
                    *)
                        exit 0
                        ;;
                esac
            fi

            TASK="Installation"
            XO_SVC="xo-proxy"

            if [[ "$PKG_FORMAT" == "rpm" ]]; then
                InstallDependenciesRPM
                InstallXOProxy
                exit 0
            fi
            if [[ "$PKG_FORMAT" == "deb" ]]; then
                InstallDependenciesDeb
                InstallXOProxy
                exit 0
            fi
            ;;

        5)
            TASK="Update"
            XO_SVC="xo-proxy"
            UpdateNodeYarn
            UpdateXO
            exit 0
            ;;
        6)
            exit 0
            ;;
        *)
            echo "Please choose one of the options"
            echo
            exit 0
            ;;
    esac

}

# Protocol to use for webserver. If both of the X.509 certificate paths are defined,
# then assume that we want to enable HTTPS for the server.
if [[ -n "$PATH_TO_HTTPS_CERT" ]] && [[ -n "$PATH_TO_HTTPS_KEY" ]]; then
    HTTPS=true
else
    HTTPS=false
fi

# Override port to 80, set https true and autocert to true if letsencrypt
if [[ "$ACME" == "true" ]]; then
    if [[ -z "$ACME_DOMAIN" ]]; then
        printfail "ACME_DOMAIN needs to be set when using ACME"
        exit 1
    fi
    PORT="80"
    HTTPS="true"
    AUTOCERT="true"
    PATH_TO_HTTPS_CERT="${PATH_TO_HTTPS_CERT:-"./certificate.pem"}"
    PATH_TO_HTTPS_KEY="${PATH_TO_HTTPS_KEY:-"./key.pem"}"
fi

# if no arguments given, we assume interactive mode.
# set here because some of the following checks either prompt user input or not.
if [[ $# == "0" ]]; then
    INTERACTIVE="true"
fi

# these functions check specific requirements and are run everytime
SelfUpgrade "$@"
ScriptInfo
CheckUser
CheckArch
CheckXE
CheckOS
CheckSystemd
CheckCertificate
# skip disk/memory check when using rollback as nothing new installed
if [[ "$1" != "--rollback" ]]; then
    CheckDiskFree
    CheckMemory
fi

if [[ $# != "0" ]]; then
    HandleArgs "$@"
    exit 0
else
    # menu starts only when no args given
    StartUpScreen
fi
ronivay commented 3 months ago

@LPJon no worries, your patch is just not needed as the script already handles this if commit is given in the branch variable :)

KSatC5 commented 3 months ago

Hi,

Yes, providing a commit (short or long hash) in the branch setting is supported. Please check the logs what actually goes wrong so i can possibly assist with this issue.

Thanks for your confirmation. Looks like I formatted it correctly either way then.

In the log file, the last line shows: fatal: not a git repository (or any of the parent directories): .git

Full log:

+ command -v git
/usr/bin/git
+ cd . && git config --get remote.origin.url
https://github.com/ronivay/XenOrchestraInstallerUpdater.git
+ cd . && git status --porcelain
 M .editorconfig
 M .github/ISSUE_TEMPLATE/feature_request.md
 M .github/ISSUE_TEMPLATE/issue.md
 M .github/dependabot.yml
 M .github/workflows/lint.yml
 M .github/workflows/main.yml
 M .github/workflows/stale.yml
 M .gitignore
 M LICENSE
 M README.md
 M sample.xo-install.cfg
Running script version a930e94 with config:

PORT="80"
INSTALLDIR="/opt/xo"
SELFUPGRADE=true
CONFIGUPDATE=true
REPOSITORY="https://github.com/vatesfr/xen-orchestra"
BRANCH="6056a618c3e503fcc0de4fe19007574e40bfddd5"
PLUGINS="all"
AUTOUPDATE="true"
OS_CHECK="true"
ARCH_CHECK="true"
PRESERVE="3"

+ id -u
0
+ uname -m
x86_64
+ command -v xe
+ grep ^VERSION_ID /etc/os-release | cut -d'=' -f2 | grep -Eo '[0-9]{1,2}' | head -1
12
+ grep ^NAME /etc/os-release | cut -d'=' -f2 | sed 's/"//g' | awk '{print $1}'
Debian
+ grep ^GRUB_DISTRIBUTOR /etc/default/grub | grep 'Xen Orchestra'
+ command -v yum
+ command -v apt-get
/usr/bin/apt-get
+ command -v systemctl
/usr/bin/systemctl
+ df -P -k '/opt' | tail -1 | awk '{print $4}'
28222868
+ grep MemTotal /proc/meminfo | awk '{print $2}'
3983680
+ pgrep -f xo-server
+ apt-get update
Hit:1 http://deb.debian.org/debian bookworm InRelease
Hit:2 http://security.debian.org/debian-security bookworm-security InRelease
Hit:3 https://deb.nodesource.com/node_18.x nodistro InRelease
Hit:4 http://deb.debian.org/debian bookworm-updates InRelease
Hit:5 https://dl.yarnpkg.com/debian stable InRelease
Reading package lists...
W: https://dl.yarnpkg.com/debian/dists/stable/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.
+ apt-get install -y build-essential redis-server libpng-dev git libvhdi-utils python3-minimal lvm2 nfs-common cifs-utils curl ntfs-3g dmidecode
Reading package lists...
Building dependency tree...
Reading state information...
build-essential is already the newest version (12.9).
redis-server is already the newest version (5:7.0.15-1~deb12u1).
libpng-dev is already the newest version (1.6.39-2).
git is already the newest version (1:2.39.2-1.1).
libvhdi-utils is already the newest version (20210425-1+b2).
python3-minimal is already the newest version (3.11.2-1+b1).
lvm2 is already the newest version (2.03.16-2).
nfs-common is already the newest version (1:2.6.2-4).
cifs-utils is already the newest version (2:7.0-2).
curl is already the newest version (7.88.1-10+deb12u5).
ntfs-3g is already the newest version (1:2022.10.3-1+b1).
dmidecode is already the newest version (3.4-1).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
+ apt-get install -y apt-transport-https ca-certificates
Reading package lists...
Building dependency tree...
Reading state information...
apt-transport-https is already the newest version (2.6.1).
ca-certificates is already the newest version (20230311).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
+ apt-get install gnupg -y
Reading package lists...
Building dependency tree...
Reading state information...
gnupg is already the newest version (2.2.40-1.1).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
+ command -v setcap
/usr/sbin/setcap
+ command -v node
/usr/bin/node
+ command -v npm
/usr/bin/npm
+ node -v 2>/dev/null| grep -Eo '[0-9.]+' | cut -d'.' -f1
18
+ command -v yarn
/usr/bin/yarn
+ /bin/systemctl enable redis-server && /bin/systemctl start redis-server
Synchronizing state of redis-server.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable redis-server
+ /bin/systemctl enable rpcbind && /bin/systemctl start rpcbind
Synchronizing state of rpcbind.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable rpcbind
+ cd "/opt/xo/xo-src/xen-orchestra" && git remote set-url origin "https://github.com/vatesfr/xen-orchestra" &&             git fetch --prune &&             git reset --hard origin/master &&           git clean -xdff 
fatal: not a git repository (or any of the parent directories): .git
ronivay commented 3 months ago

Have you for some reason deleted the content from /opt/xo/xo-src/xen-orchestra manually but left the directory there? Could you try to delete that directory completely and re-run the script. Seems that it isn't recognized as git repository content and it isn't recloned if directory exists already.

KSatC5 commented 3 months ago

Have you for some reason deleted the content from /opt/xo/xo-src/xen-orchestra manually but left the directory there? Could you try to delete that directory completely and re-run the script. Seems that it isn't recognized as git repository content and it isn't recloned if directory exists already.

Thank you. That was indeed the issue. I never deleted the contents of that folder so I'm not sure how that happened.

ronivay commented 3 months ago

Have you for some reason deleted the content from /opt/xo/xo-src/xen-orchestra manually but left the directory there? Could you try to delete that directory completely and re-run the script. Seems that it isn't recognized as git repository content and it isn't recloned if directory exists already.

Thank you. That was indeed the issue. I never deleted the contents of that folder so I'm not sure how that happened.

Great. Not sure what may have happened either, but for some reason the directory content either wasn't there or the repository information was corrupt somehow. I may look into a workaround to deal with this automatically if i ever get another similar report, but for now let's consider this resolved.