Need ideas for power on buttons for VMs


Recommended Posts

I'm trying to think of a way to power on a specific VM using a power button. I want to get it as close operating a normal PC as possible. Either wake it from the attached mouse/keyboard or some kind on custom made button or something that powers it on. Maybe it sends a WOL packet. I know sending a WOL packet from my phone is an option but that's not quite what I'm looking for. Any ideas? Anyone know what options there are? Maybe even something like a hacked Amazon Dash button or Raspberry Pi Zero or something? Or something less complicated.

Edited by bobbintb
  • Like 1
Link to comment

I have a similar need for one of my VMs that occasionally locks up. The screen and keyboard/mouse is some distance from my unRaid server so I need to find a way to force reset the vm that’s easy for the family.

 

Fortunately, I’m into home automation and have a Node-Red docker running on my server. In there, I’ll be able to set up a flow to call virsh  reset and power on commands to the unRaid server. Once that’s set up, I’ll just need to trigger them.

 

One idea is to use an amazon echo so it can be done via voice eg “Alexa, turn on the computer”.

 

another is to use a physical button such as this z-wave remote to get the job done:  https://amzn.to/2ZX1MF9

 

it's a high priority project for me so will be done soon. I’ll report back on success, or otherwise.

 

 

Link to comment
  • 10 months later...

I know this is a slightly older thread but I thought I'd share what I've done. 

 

The power button on my rig will power the system on as normal.  I'd imagine holding it once on will force a power off but I don't really want to test this - worst case, I can just pull power.  If I want to shutdown the server, I use the web gui.

 

Once unRaid is botoed, the power button will toggle my Windows VM on or off.  In Windows power management, I've set it so the power button puts the machine to sleep - this makes it start up faster.

 

First create a script in User Scripts.  I called mine vmStartStop and it toggles a VM called Windows 10.

#! /bin/bash

# if domain is running, shut down
if virsh list | grep "Windows 10 .*running" ; then
  virsh shutdown "Windows 10"

# resume domain if it's paused
elif virsh list | grep "Windows 10 .*paused" ; then
  virsh resume "Windows 10"
elif virsh list | grep "Windows 10 .*pmsuspended" ; then
  virsh dompmwakeup "Windows 10"

# otherwise start domain
else
  virsh start "Windows 10"
fi

 

 

Than edit /etc/acpi/acpi_handler.sh as per the post above.  Change the power line to point at your user script (the path is at the top of the edit script page).  Don't forget the . at the start of the line:

power) . /boot/config/plugins/user.scripts/scripts/vmStartStop/script

Hope this helps someone.

Edited by mtongnz
  • Thanks 1
Link to comment

Thanks for sharing @mtongnz. Here's my script I guess I'll share as well. This has more special haling built in for 1 GPU/multiple VM configurations to check and shutdown other VMs. In a way I like your simplified approach better but if you need to check for other running VMs you can steal from some of my functions below.

 

Use at your own risk, I'm not a coder and I don't have much bash scripting experience. Hopefully the experts on this forum can give me some feedback on what I can improve, I would really appreciate that!

 

Particularly, I'm calling this script from Home-Assistant and the only way I know how to is via SSH as the root user, would prefer a more secure solution if anybody has any suggestions.

 

Here's the User Script:

#!/bin/bash

# Script for starting stopping VMs via homeassitant
# Takes two arguments, a command (start or stop) and a VM name.
# If a start command issued, the script checks for any running VMs and shuts them down as I have a 1 GPU configuration at home
# Personally, I have this script run at array start up so it's loaded into RAM and can be called from the tmp folder by HASS, or manually
## Script includes a function to check for empty arguments or empty space and exits for the above reason (User Scripts provides an empty space as the first argument for some reason) 
comm="$1"
vm_given="$2"

#List OSX VMs for special handling
osx_vm0="MacinaboxHighSierra"

function get_vm_names {
	readarray -t vm_list < <(virsh list --all --name)
	unset vm_list[-1]
}

function get_vm_state {
	state=$(virsh domstate "$1")	
}

# This function is not currently invoked, but can be usedful for debugging
function get_vm_info {
	info=$(virsh dominfo "$1")
	echo -e "$info \n\n"
}

function check_vm_name {
	get_vm_names
	for vm in "${vm_list[@]}"
	do 
		if [[ "$vm" = "$vm_given" ]]; then
			echo "$vm_given is a valid VM name, proceding"
			return 1
		else
			:
		fi
	done
	echo "$vm_given is not a valid VM name, go home"
	exit
}

## Haven't finished writting this part yet, script will just exit at this point for OSX
## Reason for special handling is OSX doesn't shutdown when asked to by qemu
function check_if_OSX {
	if [[ "$vm_given" == "$osx_vm0" ]] || [[ "$vm_given" == "$osx_vm1" ]] || [[ "$vm_given" == "$osx_vm2" ]]; then
		echo "VM is one of listed OSX VMs, initiating special handling"
		exit
	else
		return 1
	fi
}

function start_vm {
	echo "Starting $vm_given"
	virsh start "$vm_given"
}


function shut_down_vm {
	echo -e "Sending Shutdown signal to $vm"
	virsh shutdown "$vm"
	get_vm_state "$vm"
	while [ "$state" != "shut off" ]; do
		vm_down_poll "$vm"
	done	 
}

function vm_down_poll {
	get_vm_state "$vm"	
	echo "$vm is still running"
	sleep 1
}

function loop_vms_for_shutdown {
	for vm in "${vm_list[@]}"
	do 
		get_vm_state "$vm"
		if [ "$state" == "shut off" ]
		then
			echo -e "$vm is $state"
		else
			echo -e "$vm is $state, initiaing shutdown"
			shut_down_vm "$vm"
		fi
		#Leaving this here for de-bugging purposes if needed
		#get_vm_info "$vm"
	done	
}


## Checking if arguments were supplied, otherwise exit (or shuttdown all VMs if the flag is enabled to do so)
## Arguments will be provided by HASS automation (or you can manually invoke this via command line).
## Example of how to call this script from the terminal: /tmp/user.scripts/tmpScripts/00_start_stop_VMs/script start "Ubuntu"

if [[ $# -eq 0 ]] || [[ "$1" == "" ]]; then
	if [[ shutdown_all == "enabled" ]]; then echo "No arguments supplied, shutting down all running VMs"; loop_vms_for_shutdown; else echo "No arguments provided"; fi
elif [[ "$1" == "start" ]]; then
	echo "Starting $2 VM, shutting down other running VMs first"
	check_vm_name "$2"
	loop_vms_for_shutdown
	sleep 5
	start_vm
elif [[ "$1" == "stop" ]]; then
	echo "Shutting down $2 VM"
	check_vm_name "$2"
	shut_down_vm "$2"
else
	echo "Ok I don't what you're trying to do here, $1 doesn't mean anything to me"
fi

Here's the switch configured in Home-Assistant (in configuration.yaml). Once it's an entity in HASS there are endless possibilities for adding buttons or starting/stopping VMs via automation.

switch:
  - platform: command_line
    switches:
      win10_vm:
        command_on: "ssh [email protected] '/tmp/user.scripts/tmpScripts/00_start_stop_VMs/script start \"Windows 10\"'"
        command_off: "ssh [email protected] '/tmp/user.scripts/tmpScripts/00_start_stop_VMs/script stop \"Windows 10\"'"
        command_state: "ssh [email protected] 'if [[ $(virsh domstate \"Windows 10\") == \"shut off\" ]]; then echo 1; else echo 0; fi'""
        value_template: '{{ value == "0" }}'
        friendly_name: Windows 10 VM
      ubuntu_vm:
        command_on: "ssh [email protected] '/tmp/user.scripts/tmpScripts/00_start_stop_VMs/script start \"Ubuntu\"'"
        command_off: "ssh [email protected] '/tmp/user.scripts/tmpScripts/00_start_stop_VMs/script stop \"Ubuntu\"'"
        command_state: "ssh [email protected] 'if [[ $(virsh domstate \"Ubuntu\") == \"shut off\" ]]; then echo 1; else echo 0; fi'"
        value_template: '{{ value == "0" }}'
        friendly_name: Ubuntu VM

 

  • Thanks 1
Link to comment
  • 2 weeks later...

Thanks for your script @naughty beatle it has given me some ideas. I have some iOS Shortcuts on my daughter and wife's phones which simply make an SSH call with virsh but I don't like it because they have to have my root password in there. I wanted something a bit easier like a button but Alexa and voice control might work too...

 

Did you get to the bottom of clean shutdown of MacOS? I haven't ben able to find a way to get it to respond to the qemu shutdown. I suppose you might need to have something listening inside the VM which initiates the shutdown but that feels very messy

Link to comment
  • 1 year later...
On 7/26/2020 at 7:06 PM, mtongnz said:

I know this is a slightly older thread but I thought I'd share what I've done. 

 

The power button on my rig will power the system on as normal.  I'd imagine holding it once on will force a power off but I don't really want to test this - worst case, I can just pull power.  If I want to shutdown the server, I use the web gui.

 

Once unRaid is botoed, the power button will toggle my Windows VM on or off.  In Windows power management, I've set it so the power button puts the machine to sleep - this makes it start up faster.

 

First create a script in User Scripts.  I called mine vmStartStop and it toggles a VM called Windows 10.

#! /bin/bash

# if domain is running, shut down
if virsh list | grep "Windows 10 .*running" ; then
  virsh shutdown "Windows 10"

# resume domain if it's paused
elif virsh list | grep "Windows 10 .*paused" ; then
  virsh resume "Windows 10"
elif virsh list | grep "Windows 10 .*pmsuspended" ; then
  virsh dompmwakeup "Windows 10"

# otherwise start domain
else
  virsh start "Windows 10"
fi

 

 

Than edit /etc/acpi/acpi_handler.sh as per the post above.  Change the power line to point at your user script (the path is at the top of the edit script page).  Don't forget the . at the start of the line:

power) . /boot/config/plugins/user.scripts/scripts/vmStartStop/script

Hope this helps someone.

Hello, this is very helpful! Are you able to provide any recommendations on editing the acpi_handler file on each boot? Is it just a script that runs on startup to modify that line of code? Or replace the entire acpi_handler file each time? Any example of how this can/should be done? I tried googling but am not coming up with anything that's helpful for someone without a ton of experience.

Link to comment
  • 1 month later...
On 7/27/2020 at 2:06 AM, mtongnz said:

I know this is a slightly older thread but I thought I'd share what I've done. 

 

The power button on my rig will power the system on as normal.  I'd imagine holding it once on will force a power off but I don't really want to test this - worst case, I can just pull power.  If I want to shutdown the server, I use the web gui.

 

Once unRaid is botoed, the power button will toggle my Windows VM on or off.  In Windows power management, I've set it so the power button puts the machine to sleep - this makes it start up faster.

 

First create a script in User Scripts.  I called mine vmStartStop and it toggles a VM called Windows 10.

#! /bin/bash

# if domain is running, shut down
if virsh list | grep "Windows 10 .*running" ; then
  virsh shutdown "Windows 10"

# resume domain if it's paused
elif virsh list | grep "Windows 10 .*paused" ; then
  virsh resume "Windows 10"
elif virsh list | grep "Windows 10 .*pmsuspended" ; then
  virsh dompmwakeup "Windows 10"

# otherwise start domain
else
  virsh start "Windows 10"
fi

 

 

Than edit /etc/acpi/acpi_handler.sh as per the post above.  Change the power line to point at your user script (the path is at the top of the edit script page).  Don't forget the . at the start of the line:

power) . /boot/config/plugins/user.scripts/scripts/vmStartStop/script

Hope this helps someone.

 

here how i "overwrite" it after first array start with user scripts:

 

#!/bin/bash
sed -i 's|power) /sbin/init 0|power) . /boot/config/plugins/user.scripts/scripts/vmStartStop/script|g' /etc/acpi/acpi_handler.sh

 

Link to comment
  • 4 months later...
  • 1 year later...
On 10/13/2021 at 9:55 PM, Adem said:

 

here how i "overwrite" it after first array start with user scripts:

 

#!/bin/bash
sed -i 's|power) /sbin/init 0|power) . /boot/config/plugins/user.scripts/scripts/vmStartStop/script|g' /etc/acpi/acpi_handler.sh

 

I did this but my power button still shuts down my unraid server. Any tips?

Captura de ecrã 2023-05-24 182106.png

Link to comment

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...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.