Skip to content
View in the app

A better way to browse. Learn more.

Unraid

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

libvirt hooks file - adding a routine for VM shutdown

Featured Replies

As part of my project to send GPU stats over to CoolerControl to help adjust case fans when the GPU ramps up,

I want to either Delete or Modify the txt files that the VM creates in the /tmp directory so that if they spike on shutdown (of the VM) I don't get stuck with LOUD fans for longer than necessary.

I have the script that I want to add to the /ets/libvirt/hooks/qemu file:

# Routine to delete the sensor txt values created to monitor the GPU on Minerva (VM)
GUEST_NAME="$1"
ACTION="$2"
ID="$3"

if [ "$GUEST_NAME" == "Win11 - Minerva" ]; then
    if [ "$ACTION" == "stopped" ] || [ "$ACTION" == "paused" ]; then
        # Example action: remove specific files in /tmp
        rm -f /tmp/gpu_*.txt
        # Or remove a directory
        # rm -rf /tmp/your_vm_files/
    fi
fi

But when I add that:

#!/usr/bin/env php

<?php
if (!isset($argv[2]) || $argv[2] != 'start') {
        exit(0);
}

$strXML = file_get_contents('php://stdin');

$doc = new DOMDocument();
$doc->loadXML($strXML);

$xpath = new DOMXpath($doc);

$args = $xpath->evaluate("//domain/*[name()='qemu:commandline']/*[name()='qemu:arg']/@value");

for ($i = 0; $i < $args->length; $i++){
        $arg_list = explode(',', $args->item($i)->nodeValue);

        if ($arg_list[0] !== 'vfio-pci') {
                continue;
        }

        foreach ($arg_list as $arg) {
                $keypair = explode('=', $arg);

                if ($keypair[0] == 'host' && !empty($keypair[1])) {
                        vfio_bind($keypair[1]);
                        break;
                }
        }
}

# Routine to delete the sensor txt values created to monitor the GPU on Minerva (VM)
GUEST_NAME="$1"
ACTION="$2"
ID="$3"

if [ "$GUEST_NAME" == "Win11 - Minerva" ]; then
    if [ "$ACTION" == "stopped" ] || [ "$ACTION" == "paused" ]; then
        # Example action: remove specific files in /tmp
        rm -f /tmp/gpu_*.txt
        # Or remove a directory
        # rm -rf /tmp/your_vm_files/
    fi
fi

exit(0); // end of script



function vfio_bind($strPassthruDevice) {
        // Ensure we have leading 0000:
        $strPassthruDeviceShort = str_replace('0000:', '', $strPassthruDevice);
        $strPassthruDeviceLong = '0000:' . $strPassthruDeviceShort;

        // Determine the driver currently assigned to the device
        $strDriverSymlink = @readlink('/sys/bus/pci/devices/' . $strPassthruDeviceLong . '/driver');

        if ($strDriverSymlink !== false) {
                // Device is bound to a Driver already

                if (strpos($strDriverSymlink, 'vfio-pci') !== false) {
                        // Driver bound to vfio-pci already - nothing left to do for this device now regarding vfio
                        return true;
                }

                // Driver bound to some other driver - attempt to unbind driver
                if (file_put_contents('/sys/bus/pci/devices/' . $strPassthruDeviceLong . '/driver/unbind', $strPassthruDeviceLong) === false) {
                        file_put_contents('php://stderr', 'Failed to unbind device ' . $strPassthruDeviceShort . ' from current driver');
                        exit(1);
                        return false;
                }
        }

        // Get Vendor and Device IDs for the passthru device
        $strVendor = file_get_contents('/sys/bus/pci/devices/' . $strPassthruDeviceLong . '/vendor');
        $strDevice = file_get_contents('/sys/bus/pci/devices/' . $strPassthruDeviceLong . '/device');

        // Attempt to bind driver to vfio-pci
        if (file_put_contents('/sys/bus/pci/drivers/vfio-pci/new_id', $strVendor . ' ' . $strDevice) === false) {
                file_put_contents('php://stderr', 'Failed to bind device ' . $strPassthruDeviceShort . ' to vfio-pci driver');
                exit(1);
                return false;
        }

        return true;
}

But when I try to run the VM I get:

image.png

[Hook script execution failed: internal error: Child process (LC_ALL=C PATH=/bin:/sbin:/usr/bin:/usr/sbin HOME=/root /etc/libvirt/hooks/qemu 'Win11 - Minerva' prepare begin -) unexpected exit status 255]

Is there a simple answer as to where I've gone wrong?

Thank You

Arbadacarba

Edited by Arbadacarba

  • Author

Might help if my addition hadn't been written in bash I guess...

  • Community Expert

You cannot put bash into PHP.

But you can add additional scripts here

ls /etc/libvirt/hooks/qemu.d/

ArcReset Notify* Savehook USB_Manager* VMTest savehook.php*

Note if the script hangs then the VM process will hang.

  • Author

Ya, the bash thing was dumb... I've got some of it working in php, but I can't figure out how to get it to act if I PAUSE the vm... I've got it working if I stop it but that's only half the plan...

If I create an additional script does it have to be in PHP? or can it be bash? I thought I had a way to detect pause in bash.

Arbadacarba

  • Community Expert
5 hours ago, Arbadacarba said:

Ya, the bash thing was dumb... I've got some of it working in php, but I can't figure out how to get it to act if I PAUSE the vm... I've got it working if I stop it but that's only half the plan...

If I create an additional script does it have to be in PHP? or can it be bash? I thought I had a way to detect pause in bash.

Arbadacarba

Here is a link to the hooks documentation, but dos not look like one for the VM being paused.

  • Author

That's why I was wondering if you can call a bash script from the hooks file

image.png

Thanks for your help Simon... Did you mean to add a link in the previous post?

  • Community Expert
4 hours ago, Arbadacarba said:

That's why I was wondering if you can call a bash script from the hooks file

image.png

Thanks for your help Simon... Did you mean to add a link in the previous post?

Yes I did libvirt.org/hooks.html Yes I think it may be easier in bash if you don't know PHP, there are ways to execute shell cmds in PHP.

  • Author

Looking through that I'm impressed at how I think the scripts work... but at the same time I might not be able to take advantage of it since it doesn't have all the features that I need...

So we can create scripts - Bash or PHP etc. That depending on the folder they are located in, can run when the referenced VM makes transition to Start, or Stop... but there is no provision to call a script when it is paused?

Hmm. so I pause the VM when the AMP input switches to t different source so that wehn it gets switched back it comes up faster... So the script would not run in that case and my cooling system would continue to act as if the temps were remaining the same.

What about the network hooks? Could a script be triggered when the VM loses connection? It mentions being unplugged, and when I pause the VM it vanishes from my network...

Thanks

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.