Como o systemd pode iniciar e controlar automaticamente os convidados do VirtualBox?

1

No meu caso particular, com uma nova instalação de servidor do Ubuntu 18.04 Bionic e do VirtualBox-5.2.20, parece que o velho método de iniciar automaticamente os convidados não está mais disponível. Não que isso fosse maravilhoso - mas funcionava. Não parece haver nenhuma maneira limpa de fazer isto - como o systemd e o VirtualBox podem trabalhar juntos para inicialização, controle e desligamento inteligentes?

    
por Daniel Miller 08.11.2018 / 05:02

1 resposta

0

Bem ... acho que surgiu uma resposta.

Esta é a minha solução. Certamente não é perfeito - e parte da razão pela qual estou compartilhando é convidar a melhoria. No entanto, isso permite a inicialização automática, monitoramento e desligamento via systemd. E eu acho que isso está indo na direção certa para esses dois produtos.

Uma ressalva - o abaixo pressupõe um pouco de familiaridade com ambos systemd & VirtualBox. Ele também requer que as funções de desligamento da ACPI sejam ativadas nos convidados. Isso pode ser embutido no Windows e tão simples quanto instalar o acpid no Linux, mas eu não estou assumindo. Também alguns convidados (versão do Windows xxxx) podem precisar de alguns "ajustes" para garantir que os desligamentos da ACPI aconteçam imediatamente - eu encontrei um recurso maravilhoso em link

Primeiro - é necessário criar uma unidade de sistema claro. Estou aproveitando a disponibilidade de modelos .

a execução de systemctl edit --full [email protected] fornece um editor no qual colocamos:     [Unidade]     Descrição = VirtualBox% I Virtual Server     Depois = network.target vboxdrv.service

[Service]
Type=forking
Restart=no
TimeoutSec=5min
KillMode=process
RuntimeDirectory=vbox
RuntimeDirectoryPreserve=yes
PIDFile=/run/vbox/%I.pid

Environment='RUNDIR=/run'
Environment='PIDDIR=/vbox'
Environment='VM=%I'
ExecStart=/etc/init.d/vbox-systemd start
ExecStop=/etc/init.d/vbox-systemd stop

[Install]
WantedBy=multi-user.target

O texto acima fornece uma base:

- Allows for up to 5 minutes for startup/shutdown per guest
- The pid files will be stored as /run/vbox/<guest>.pid
- And the guests will be started as part of the normal boot process

Isso pode ser ajustado a gosto - mas, além dos padrões para todo o servidor, deixe isso de lado. Convidados individuais serão adaptados mais tarde. Agora - precisa fornecer o script auxiliar. Eu passei um longo período de tempo lutando com os meandros da BASH, falta de sono e uma grave falta de experiência ativa com a BASH. Portanto, os seguintes trabalhos, há uma mistura de estilos, e eu realmente gostaria de saber por que minha tentativa de funções simples do BASH falhou tão miseravelmente. Mas estou pronta para dormir, embora não seja o meu melhor trabalho ... funciona!:

#! /bin/bash
# /etc/init.d/vbox-systemd: Helper script to startup & shutdown VirtualBox
# headless machines via systemd
#
# written by Daniel L. Miller <[email protected]>

# This should not be called directly (though possible with the
# proper environment variables set). This is used by the
# [email protected] template to start & stop virtual machines - 
# with supervision.

# Environment variables to be defined for us by systemd unit
# RUNDIR=/run
# PIDDIR=/vbox
# VM=<vmname>

# This was setup to use environment variables - maybe support cmd line as well.
if [ ! -z "$2" ]; then
    VM=$2
fi

# So...I suppose might as well set sane defaults
if [ -z "$RUNDIR" ]; then
    RUNDIR='/run'
fi
if [ -z "$PIDDIR" ]; then
    PIDDIR='/vbox'
fi

#
# Overprotective but trying to be good...
# These utilities should be fairly standard...
#
VB=/usr/bin/VBoxManage
GREP=/bin/grep
CUT=/usr/bin/cut
TR=/usr/bin/tr
SLEEP=/bin/sleep
WAITEXIT=300

# Make sure the utilities are available
test -x $VB || exit 3
test -x $GREP || exit 3
test -x $CUT || exit 3
test -x $TR || exit 3

# Verify the pid folder tree is defined and usable
test -d "${RUNDIR:?run directory top-level must be set}" || exit 3
test -d "$RUNDIR${PIDDIR:?pid directory must be set}" || mkdir -p "$RUNDIR$PIDDIR"
# This test is a little different - this validates the name but we don't
# care if the file exists or not. At least the moment.
test -f "$RUNDIR$PIDDIR/${VM:?Virtual Machine name must be set}.pid"

PIDFILE=$RUNDIR$PIDDIR/$VM.pid

vmactive=$($VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"')

case "${1:-''}" in
  'start')
    # Start the machine
    $VB startvm $VM --type headless
    # Give it at least a change to get started...
    $SLEEP 2
    # Now perform first trick and save pid
    vmactive='$VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"''
    if [ "x$vmactive" == "x$VM" ]; then
        vmpid=$($VB showvminfo $VM --log 0 | $GREP -m 1 'Process ID' | $CUT -d ':' -f4 | $TR -d ' ')
        echo $vmpid > $PIDFILE
    else
        exit 1;
    fi
    ;;
  'stop')
    waited=0
    while [ "$waited" -lt $WAITEXIT ]; do
        # Test first so VB doesn't object to shutting off a non-running VM
        vmactive='$VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"''
        if [ "x$vmactive" != "x$VM" ]; then
            echo "Proper ACPI Shutdown of $VM - or it wasn't running!"
            break
        fi
        # Try to turn it off - repeatedly
        $VB controlvm $VM acpipowerbutton
        # Give it a chance to take.
        $SLEEP 5
        waited=$((waited+5))
    done

    # Time to clean up - force terminate if necessary and delete the pid file
    [ "$waited" -ge $WAITEXIT ] && [ -f $PIDFILE ] && kill -s 9 $PIDFILE
    [ -f $PIDFILE ] && rm $PIDFILE
    ;;
  'status')
    vmactive='$VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"''
    if [ "x$vmactive" == "x$VM" ]; then
        vmpid=$($VB showvminfo $VM --log 0 | $GREP -m 1 'Process ID' | $CUT -d ':' -f4 | $TR -d ' ')
        echo "$VM is running as PID $vmpid"
    else
        echo "$VM is not running"
    fi
    ;;
  *)
    echo "Usage: vbox-systemd [start|stop|status]" >&2
    exit 3;
    ;;
esac

Então ... agora tudo que é necessário para iniciar uma máquina virtual é: systemctl start vbox@<your-guest-name> . Mais empolgante - systemctl status vbox@<your-guest-name> fornecerá o status do systemd da VM! E você pode até mesmo fazer um systemctl stop vbox@<your-guest-name> para desativá-lo.

Para ativar o início automático, basta executar systemctl enable vbox@<your-guest-name> .

Agora - se você precisar de um controle extra, como especificar a ordem na qual os convidados inicializam, use o complicado systemctl edit vbox@<your-guest-name> . Observe que desta vez não estamos usando o argumento --full - isso cria uma pasta de substituição apenas para este convidado sem duplicar a unidade base. Talvez este convidado precise de serviços SQL do host:

[Unit]
After=mysql.service
Wants=mysql.service

Agora este convidado não será iniciado até que o servidor mysql esteja ativo. Ou, se esse convidado fornecer serviços essenciais, você poderá adicionar:

[Services]
Restart=yes

Lembre-se - basta colocar os argumentos do systemd que você precisa adicionar ou sobrescrever - o resto vem do modelo.

Espero que isso ajude alguém - e se outros puderem contribuir, por favor, faça!

    
por 08.11.2018 / 05:27