[TUTO] How to start 12 VirtualBox Guests in a single command

Share your own howto's etc. Not for support questions!

[TUTO] How to start 12 VirtualBox Guests in a single command

Postby DoubleHP » 2017-03-27 02:24

I wanted to have 12 VirtualBox Guests.

During VB updates, it's required to shutdown all guests. I also wanted to do that in a single command; not having to type "stop" 12 times.

We need to create two unit files: The main "all" service:

Code: Select all
# cat /etc/systemd/system/virtualbox-leon-all.service | grep -v "^#"
[Unit]
Description=VirtualBox Leon-all machine ...
Requires=ssh.service
After=ssh.service

[Service]
Type=oneshot
ExecStart=/bin/true

[Install]
WantedBy=multi-user.target


And a generic guest:

Code: Select all
# cat /etc/systemd/system/virtualbox-leon-04.service | grep -v "^#"
[Unit]
Description=VirtualBox %N machine ...
Requires=ssh.service
After=ssh.service
PartOf=virtualbox-leon-all.service

[Service]
Type=simple
ExecStart=/bin/bash -c "/usr/bin/VBoxHeadless -s Leon-$(echo %N | cut -d '-' -f3)"
Restart=always
ExecStop=/bin/bash -c "/usr/local/bin/virtualbox_stop_vm.sh Leon-$(echo %N | cut -d '-' -f3)"
TimeoutStopSec=200s
KillMode=none

[Install]
WantedBy=multi-user.target
WantedBy=virtualbox-leon-all.service


The guest service file must be in /etc/systemd/system/ ; it can not be stored outside and linked to here.

Now, copy the guest files as many times as you want, to get this:

Code: Select all
# for i in 07 08 09 10 11 12 ; do cp -a /etc/systemd/system/virtualbox-leon-04.service /etc/systemd/system/virtualbox-leon-${i}.service  ; done
# ll /etc/systemd/system/
total 92
drwxr-xr-x 2 root root 4096 Jun 25  2016 getty@.service.d
drwxr-xr-x 2 root root 4096 Jun 25  2016 getty.target.wants
drwxr-xr-x 2 root root 4096 Mar 27 03:27 multi-user.target.wants
drwxr-xr-x 2 root root 4096 Jun 25  2016 network-online.target.wants
drwxr-xr-x 2 root root 4096 Jun 25  2016 paths.target.wants
drwxr-xr-x 2 root root 4096 Jul 10  2016 remote-fs.target.wants
lrwxrwxrwx 1 root root    9 Dec  1 09:54 samba-ad-dc.service -> /dev/null
drwxr-xr-x 2 root root 4096 Jun 25  2016 sockets.target.wants
-rw-r--r-- 1 root root  507 Jul 10  2016 ssh.service
drwxr-xr-x 2 root root 4096 Jun 25  2016 sysinit.target.wants
lrwxrwxrwx 1 root root   35 Jun 25  2016 syslog.service -> /lib/systemd/system/rsyslog.service
drwxr-xr-x 2 root root 4096 Jun 25  2016 timers.target.wants
lrwxrwxrwx 1 root root    9 Dec 27 19:37 vboxweb.service -> /dev/null
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-02.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-03.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-04.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-05.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-06.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-07.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-08.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-09.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-10.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-11.service
-rw-r--r-- 1 root root  879 Mar 27 03:16 virtualbox-leon-12.service
-rw-r--r-- 1 root root 1368 Mar 27 03:06 virtualbox-leon-all.service
drwxr-xr-x 2 root root 4096 Mar 27 03:27 virtualbox-leon-all.service.wants


Enable the all service, and some guests:

Code: Select all
# systemctl enable virtualbox-leon-all.service
# systemctl enable virtualbox-leon-02.service
# systemctl enable virtualbox-leon-03.service
# systemctl enable virtualbox-leon-04.service
# systemctl enable virtualbox-leon-05.service
# ll /etc/systemd/system/virtualbox-leon-all.service.wants/
total 0
lrwxrwxrwx 1 root root 46 Mar 27 03:27 virtualbox-leon-02.service -> /etc/systemd/system/virtualbox-leon-02.service
lrwxrwxrwx 1 root root 46 Mar 27 03:27 virtualbox-leon-03.service -> /etc/systemd/system/virtualbox-leon-03.service
lrwxrwxrwx 1 root root 46 Mar 27 03:27 virtualbox-leon-04.service -> /etc/systemd/system/virtualbox-leon-04.service
lrwxrwxrwx 1 root root 46 Mar 27 03:27 virtualbox-leon-05.service -> /etc/systemd/system/virtualbox-leon-05.service


Note that I did not enable all guests. Start all:
Code: Select all
# systemctl start virtualbox-leon-all.service

and enjoy all process:

Code: Select all
# psa virtua

        * I remind you that With NPTL ps and top no longer show threads. You can use any of: '-m m -L -T H' in ps or the H key in top to show them.
        * also try: ps axjf

c="ps -eo user,pid,ppid,%cpu,%mem,vsz,rss,size,tty,nice,nlwp,psr,sgi_p,bsdstart,bsdtime,args k start_time"
m
root      5999     1  0.1  0.1 244600  8872 19188 ?          0    1   1 *  00:30   0:29 /usr/lib/virtualbox/VBoxXPCOMIPCD
root      6005     1  0.3  0.2 1006180 16868 34844 ?         0   17   1 *  00:30   1:01 /usr/lib/virtualbox/VBoxSVC --auto-shutdown
root      7016  7014  0.5  0.6 1334064 52632 134884 ?        0   14   0 *  00:33   1:22 /usr/lib/virtualbox/VirtualBox
root     30455     1  7.9  3.4 2059288 270148 116088 ?       0   30   1 *  03:28   7:05 /usr/lib/virtualbox/VBoxHeadless -s Leon-05
root       398     1  8.1  3.0 1999412 242812 115924 ?       0   30   0 *  03:32   6:58 /usr/lib/virtualbox/VBoxHeadless -s Leon-04
root       494     1  179 23.5 6307104 1858272 152796 ?      0   34   1 *  03:32 153:09 /usr/lib/virtualbox/VBoxHeadless -s Leon-03
root       515     1 33.8  1.3 1949168 104148 109912 ttyS0   0   31   0 *  03:32  28:51 /usr/lib/virtualbox/VBoxHeadless -s Leon-02


Note that it could be possible to have a more simple ExecStart= by matching all the names (name of unit must exactly match the name of guest in VB, including case). I had to trick because I created my VMs long time ago, and done these units recently.

Also, the guest units can probably hard links; I did not try; would be easier to update them.

Finaly, I have to also publish my stop script:

Code: Select all
# cat /usr/local/bin/virtualbox_stop_vm.sh
#!/bin/bash

[ "$1" = "" ] && {
        echo "$0: needs an argument: VM to be turned off".
        exit 1
}

logfile="/dev/shm/$(basename "$0").$1.$(/bin/date +%Y-%m-%d_%H-%M-%S)"

echo "*Begin."
n=25
while [ $n -gt 0 ]
do
        /usr/bin/VBoxManage controlvm "$1" acpipowerbutton &
        /bin/sleep 3
        n=$(($n-1))
        pid=$!
        /bin/sleep 3
        [ -d /proc/${pid} ] && n=0
echo ".s"
        /usr/bin/VBoxManage showvminfo "$1" | /bin/grep "^State:" >"${logfile}" &
        /usr/local/bin/wait_pid_or_kill.sh $! 2
        cat "${logfile}" | /bin/grep -e "stopping" -e "powered off" -e "aborted" >/dev/null && n=-1
        echo "*n: $n"
done
echo "***n: $n"

[ $n -le 0 ] && /usr/bin/VBoxManage controlvm "$1" poweroff &
pid="$(ps aux | grep -i virtua | grep -v "$0" | grep "$1" | awk '{print $2}')"
echo "*PID: $pid"
[ "$pid" != "" ] && {
        sleep 10
        pid="$(ps aux | grep -i virtua | grep -v "$0" | grep "$1" | awk '{print $2}')"
        echo "*PID: $pid"
        [ "$pid" != "" ] && {
                echo "Need to kill $pid :"
                ps aux | grep -i virtua | grep "$1" | grep -v "$0"
                kill $pid
                }
        sleep 10
        }
echo "*END."


The latency is designed to accept two timing issues:
- process taking long time to terminate in the guest
- if we ask for a stop, just after a start, and, during guest initialisation, a small fsck is run

I could not make these latencies too long, because, we still need to terminate the guests before the UPS goes out of battery.

It's far from perfect, but considering how old the tutos are in Google, this may help some people in the future.

If yout unit file can have exactly the same name as the VirtualBox guest name, the exec lines can become more simple:
Code: Select all
ExecStart=/bin/bash -c "/usr/bin/VBoxHeadless -s "%N"
ExecStop=/bin/bash -c "/usr/local/bin/virtualbox_stop_vm.sh "%N"


Ah, also need to provide wait_pid ...

Code: Select all
# cat wait_pid_or_kill.sh
#!/bin/bash

[ "$1" = "" ] && {
        echo "$0 requires first argument a PID."
        exit 1
}
[ "$2" = "" ] && {
        echo "$0 requires second argument a timeout in s."
        exit 1
}
[ "$1" = "-h" -o "$2" = "-h"  ] && {
        echo "$0 Wait for a PID to terminate, or kill it after timeout."
        exit 0
}

pid=$1
time=$2
[ $pid -gt 0 ] || {
        echo "$0 First argument does not seem a number"
        exit 1
}
[ $time -gt 0 ] || {
        echo "$0 Second argument does not seem a number"
        exit 1
}

i=$time
while [ $i -gt 0 ]
do
        sleep 1
        i=$(($i-1))
        [[ -d /proc/$pid ]] || break
done

[ $i -gt 0 ] && exit 0

basename "$0" | grep "die" >/dev/null  && exit 1
basename "$0" | grep "kill" >/dev/null && [ -d /proc/$pid ] && kill $pid


This script can be stored as wait_pid_or_kill.sh, then make a symlink from wait_pid_or_die.sh. The first one will kill the process we are waiting for; the second will return an error without killing if still alive after the timeout.
DoubleHP
 
Posts: 14
Joined: 2016-10-09 08:55

Re: [TUTO] How to start 12 VirtualBox Guests in a single com

Postby Head_on_a_Stick » 2017-03-27 06:15

Is this a support request or a HowTo?

If it is a guide, it should be moved to the correct section, I can do this if you want :)

Also, have you seen https://wiki.debian.org/KVM?

Virtual machines can be handled directly by systemd using machinectl(1).
“Controlling complexity is the essence of computer programming."Brian Kernighan

Please read before posting How to report a problem
User avatar
Head_on_a_Stick
 
Posts: 6491
Joined: 2014-06-01 17:46
Location: /dev/chair

Re: [TUTO] How to start 12 VirtualBox Guests in a single com

Postby DoubleHP » 2017-03-27 17:02

Yes, you can if you want. I was just sharing some scripts. Systemd is a bit weird at the beginning; but once you have read the whole doc, it can do wonderfull things. It's not really a clean guide-tutorial. More like a logbook.
DoubleHP
 
Posts: 14
Joined: 2016-10-09 08:55


Return to Docs, Howtos, Tips & Tricks

Who is online

Users browsing this forum: dadwhiskers and 4 guests

fashionable