Using the pct/qm command within a hook script

JanWiesemann

New Member
Mar 2, 2022
6
0
1
27
I'm trying to run some pct commands inside of a hook-script. Sadly, this isn't woking, since PVE is still locking the container at this point in time and thus I'm unable to execute any pct/qm commands inside of my hook.

Is there something like a 'ignore locks' feature or flag?

Script:
Bash:
#!/bin/bash

vmid=$1
pase=$2

if ! [[ $vmid =~ ^[1-9][0-9]{2,}$ ]]; then
    echo "argument 1 has to be a valid VMID! $vmid"
    exit 1
fi

if [[ "$phase" != "" ]] && [[ "$phase" != "post-start" ]]; then
    echo "pve hook-script not invoked in phase 'post-start'! $phase"
    exit 0
fi

echo
echo "=== Copy SSH settings to guest $vmid ==="

statusMessage=$(pct status $vmid)
if ! [[ $statusMessage = "status: running" ]]; then
    if [[ $statusMessage = "status: stopped" ]]; then
        echo "guest $vmid not running!"
    elif [[ $statusMessage != "" ]]; then
        echo "$statusMessage"
    fi

    echo
    exit 1
fi

set -e

echo "generating host keys..."
pct exec $vmid -- /bin/bash -c "cd ~/ && ssh-keygen -A -vvv"
echo

echo "copy sshd_config..."
pct push $vmid lxc-ssh-set-defaul-settings-sshd_config /etc/ssh/sshd_config
echo "restarting sshd..."
pct exec $vmid -- /bin/bash -c "systemctl restart ssh"
echo

echo "creating ~/.ssh directory..."
pct exec $vmid -- /bin/bash -c "mkdir -p -v ~/.ssh"
echo "copy authorized_keys..."
pct push $vmid lxc-ssh-set-defaul-settings-authorized_keys ~/.ssh/authorized_keys
echo

echo "done!"
echo

Log:
Code:
pve hook-script not invoked in phase 'post-start'!

=== Copy SSH settings to guest 103 ===
generating host keys...

copy sshd_config...
trying to acquire lock...
can't lock file '/run/lock/lxc/pve-config-103.lock' - got timeout
hookscript error for 103 on post-start: command '/mnt/pve/pve-share/snippets/lxc-ssh-set-defaul-settings.sh 103 post-start' failed: exit code 4

TASK OK

EDIT: workaround by using lxc-attach and a long DuckDuckGo session:
Bash:
#!/bin/bash

vmid=$1
phase=$2

basedir=$(dirname -- "$0")

if ! [[ $vmid =~ ^[1-9][0-9]{2,}$ ]]; then
    echo "argument 1 has to be a valid VMID! $vmid"
    exit 1
fi

if [[ "$phase" != "" ]] && [[ "$phase" != "post-start" ]]; then
    exit 0
fi

echo
echo "=== Copy SSH settings to guest $vmid ==="

statusMessage=$(pct status $vmid)
if ! [[ $statusMessage = "status: running" ]]; then
    if [[ $statusMessage = "status: stopped" ]]; then
        echo "guest $vmid not running!"
    elif [[ $statusMessage != "" ]]; then
        echo "$statusMessage"
    fi

    echo
    exit 1
fi

set -e

echo "generating host keys..."
lxc-attach -n $vmid -- /bin/bash -c "cd ~/ && ssh-keygen -A -vvv"

echo "copy sshd_config..."
cat "$basedir/lxc-ssh-set-defaul-settings-sshd_config" | lxc-attach -n $vmid -- bash -c "cat > /etc/ssh/sshd_config"

echo "creating ~/.ssh directory..."
lxc-attach -n $vmid -- /bin/bash -c "mkdir -p -v ~/.ssh"
echo "copy authorized_keys..."
cat "$basedir/lxc-ssh-set-defaul-settings-authorized_keys" | lxc-attach -n $vmid -- bash -c "cat > ~/.ssh/authorized_keys"

#If invoked as hook-script, sshd is not yet started and we don't need to start it.
#If invoked after startup, we need to reload sshd
if [[ "$phase" = "" ]]; then
    echo "restarting sshd..."
    lxc-attach -n $vmid -- /bin/bash -c "systemctl restart ssh"
fi

echo "done!"
echo
 
Last edited:
I had a similar problem running qm destroy in a post-stop and solved it by running it concurrently with nohup:
Bash:
#!/bin/bash
if [ "$2" == "pre-start" ]
then
    echo "VM $1 will self-destruct after shutdown!"
elif [ "$2" == "post-stop" ]
then
    nohup /usr/sbin/qm destroy "$1" &>/dev/null &
fi
Maybe something like that can for you as well? Another alternative I use when starting a VM using a script is to do qm guest exec in a loop after starting the VM:
Bash:
until qm guest exec "$1" "echo" "Hello world!" 1>&2
do
    sleep 1
done