From standalone QEMU to libvirt managed QEMU

libvirtlogoNel precedente post abbiamo introdotto libvirt parlando della sua architettura e delle funzionalità che offre, ora ci occuperemo della migrazione da una configurazione con macchine virtuali già installate e funzionanti gestite direttamente dalla riga di comando o tramite degli script (argomento trattato in questo mio precedente post) ad una configurazione gestita tramite libvirt e la sua management console virsh.

Per utilizzare con profitto le funzionalità di libvirt con KVM come hypervisor vi raccomando di avere una distribuzione abbastanza up-to-date visto che sia il virtualizzatore che la libreria con tutti i suoi tools sono software il cui sviluppo procede ancora spedito, in seguito utilizzerò una Ubuntu 9.04.

Installazione

Facendo la premessa che la versione pacchettizzata per la vostra distribuzione sia sufficientemente stabile, integri tutte le feature di cui necessitiate, etc, etc…potreste voler installare tutto il software necessario dai repository della vostra distribuzione. Tutto ciò di cui necessitate è installabile col seguente comando:

sudo apt-get install virt-manager virt-viewer kvm libvirt-bin libvirt-doc virt-top

Configurazione

Il primo step è quello di definire un dominio per l’immagine che volete utilizzare. Ipotizziamo di utilizzare la rete in modalità bridged e che utilizziate una riga di comando simile alla seguente per avviare la macchina virtuale:

sudo qemu-system-x86_64 -drive file=/media/sda5/vm/img/hellgate.img,if=ide,boot=on
        -net nic,model=virtio,macaddr=52:54:00:12:34:56 -net tap -usb -k it -localtime -smp 1 -m 512

Ci sono essenzialmente due modi per creare la configurazione del domain: il primo è utilizzando virt-install, il secondo di scrivere manualmente il file xml che definisce la macchina virtuale.

Nel primo caso basta digitare alla riga di comando quanto segue:

sudo virt-install -n hellgate -r 512 --vcpus=2
        --disk path=/media/sda5/vm/img/hellgate.img,bus=ide,device=disk
        --accelerate --vnc --keymap=it --noautoconsole --hvm
        --network bridge:br0 --mac=52:54:00:12:34:56 --cdrom /dev/null

Il precedente comando crea ed avvia da cdrom una macchina virtuale: col nome indicato dal parametro -n, la quantità di ram indicata dal parametro -r ed il numero di cpu indicate dal parametro –vcpus. Col parametro –disk si indica il path al file immagine, il tipo di bus che intendiamo utilizzare (nel caso del virtualizzatore da noi utilizzato le possibilità sono virtio, ide e scsi) ed il tipo di device da mostrare al guest ( nel nostro caso la scelta è fra floppy, disk e cdrom). Con –accelerate indichiamo che vogliamo sfruttare l’accelerazione da parte del nostro kernel, con –vnc che vogliamo utilizzare un server VNC anziché una finestra SDL, con –keymap specifichiamo il layout della tastiera che verrà utilizzata dal guest, con –noautoconsole specifichiamo che non vogliamo connessioni automatiche alla console della macchina virtuale, con –hvm indichiamo che vogliamo un guest full-virtualized. Con –network la tipologia di rete e la configurazione che vogliamo, in questo caso la rete è in modalità bridged, con –mac il mac precedentemente assegnato al guest. Infine con –cdrom il valore farlocco dell’unità ottica.

Risultato analogo si può ottenere andando ad aggiungere una macchina virtuale da virt-manager, tenete presente però che in entrambi i casi difficilmente la procedura di creazione automatica avvierà QEMU esattamente con la riga di comando che volete voi, quindi sarà comunque necessario intervenire manualmente sul file di configurazione della macchina virtuale.

Altra cosa: virt-install definisce un xml dai parametri passatigli e poi avvia in automatico la macchina virtuale facendola avviare da cdrom, ovvio che se per aggiungere una macchina virtuale da un disco pre-esistente avete messo come cdrom /dev/null il tentativo di avviare la vm non andrà a buon fine, quindi al primo avvio arrestate il domain e riavviatelo in seguito.

Per connettervi alla macchina virtuale così creata basta usare virt-viewer seguito dal nome assegnato al dominio.

Risultato analogo e con più o meno la stessa sintassi si può ottenere con virt-image, a voi la scelta su quale tool utilizzare, io personalmente preferisco definire il file xml manualmente come vedremo ora.

Altra strada percorribile è quella di scrivere direttamente il file xml che definisce il dominio, nel caso in cui utilizziate una riga di comando simile alla precedente il template da utilizzare è simile al seguente:

     1	<domain type='kvm'>
     2	  <name>hellgate</name>
     3	  <uuid>06f0ac5a-11ea-4f1f-af42-74dce39427eb</uuid>
     4	  <memory>524288</memory>
     5	  <currentMemory>524288</currentMemory>
     6	  <vcpu>1</vcpu>
     7	  <os>
     8	    <type arch='x86_64' machine='pc'>hvm</type>
     9	    <boot dev='hd'/>
    10	  </os>
    11	  <features>
    12	    <acpi/>
    13	    <apic/>
    14	    <pae/>
    15	  </features>
    16	  <clock offset='localtime'/>
    17	  <on_poweroff>destroy</on_poweroff>
    18	  <on_reboot>restart</on_reboot>
    19	  <on_crash>destroy</on_crash>
    20	  <devices>
    21	    <emulator>/usr/bin/kvm</emulator>
    22	    <disk type='file' device='disk'>
    23	      <source file='/media/sda5/vm/img/hellgate.img'/>
    24	      <target dev='hda' bus='ide'/>
    25	    </disk>
    26	    <interface type='bridge'>
    27	      <mac address='52:54:00:12:34:56'/>
    28	      <source bridge='br0'/>
    29	      <target dev='tap0'/>
    30	      <model type='virtio'/>
    31	    </interface>
    32	    <input type='tablet' bus='usb'/>
    33	    <input type='mouse' bus='ps2'/>
    34	    <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='it'/>
    35	  </devices>
    36	</domain>
  • 1-6: L’elemento domain costituisce la root del file, nell’attributo type bisogna specificare il tipo di hypervisor che si vuole impiegare (kvm, kqemu, xen…), nel contenuto dell’elemento name mettiamo il nome che intendiamo assegnare al guest, nel contenuto dell’elemento uuid inseriamo l’identificatore univoco globale della macchina virtuale, se creiamo il file di configurazione con virt-install l’uuid viene generato automaticamente, invece definendo il file di configurazione è necessario generarne una valida in qualche modo, per fare ciò utilizzate il comando uuidgen fornito out-of-the-box nelle ubuntu. Successivamente è necessario definire alcune semplici caratteristiche della macchina virtuale, nell’elemento memory indicate il massimo ammontare della ram disponibile per il domain, nel campo currentMemory indicate l’ammontare della memoria inizialmente allocata alla macchina virtuale, ciò permette di sfruttare la feature del memory ballooning disponibile in alcuni hypervisor, inutile dire che deve essere inferiore o al limite uguale alla memoria massima disponibile per il guest definita alla riga 5.
  • 7-10: I valori definiti all’interno dell’elemento os definiscono il tipo di macchina che si vuole mostrare al guest (32bit o a 64bit, pc o isapc…) e se la macchina virtuale in corso di definizione deve essere para-virtualized o fully-virtualized (nel caso dell’hypervisor oggetto di questa guida il valore da inserire è hvm ad indicare che il guest deve essere fully-virtualized), con l’elemento boot definiamo il device da cui vogliamo avviare la macchina virtuale, è possibile ripetere questo elemento per definire una lista prioritaria di periferiche di boot.
  • 11-16: All’interno dell’elemento features andiamo a definire alcune caratteristiche della macchina virtuale, per avere un elenco completo ed esaustivo delle caratteristiche supportate dal vostro hypervisor digitate alla console virsh capabilities. Succesivamente con l’elemento clock si definisce la strategia di inizializzazione dell’orologio della macchina virtuale, è consigliato utilizzare localtime per le macchine windows e utc per gli altri os, tuttavia non ho notato malfunzionamenti di sorta ad indicare localtime anche per macchine virtuali non windows-based.
  • 17-19: Ora è necessario specificare alcune strategie di lifecycle management, per i tre elementi (on_poweroff, on_reboot, on_crash) i valori assegnabili sono destroy, restart, preserve, rename-restart abbastanza autoesplicativi, se necessitate di ulteriori informazioni potete dare un’occhiata alla documentazione indicata.
  • 20-25: Ora iniziamo a definire i device da mostrare al guest, l’elemento emulator ci serve per indicare il path assoluto al virtualizzatore, nel caso in cui non lo conosciate il comando virsh capabilities vi indicherà che valore assegnare. Successivamente definiamo la configurazione del disco, nel nostro specifico caso definiamo un disco indicando che si tratta di un file (valori possibili file e block) e che si tratta di un disco, le tipologie di device sono floppy, disk e cdrom. Definiamo il path dell’immagine disco all’interno del filesystem (nel caso in cui precedentemente abbiate selezionato un device fisico col valore block per l’attributo type l’attributo da definire è dev e non file), infine con l’elemento target definiamo l’ordine del device, attributo dev, e il tipo di bus che può assumere un qualsiasi valore fra ide, scsi, virtio, xen o usb, nel caso in cui il vostro guest supporti virtio per i device a blocchi (al momento linux) vi consiglio la lettura di questo mio post riguardante la configurazione del guest.
  • 26-31: Veniamo ora alla configurazione della rete, in questo caso specifico la rete è in modalità bridged, specifichiamo il mac address dell’interfaccia di rete, il nome dell’interfaccia tunnel e del bridge a cui agganciarla, infine con l’elemento model definiamo il tipo di interfaccia, per l’elenco delle interfacce supportate da qemu in ubuntu dovete eseguire  qemu -net nic,model=? /dev/null, comunque vi consiglio di scegliere fra rtl8139, e1000 e virtio, nel caso in cui scegliate virtio date un’occhiata a questi miei post in cui tratto l’installazione e la configurazione dei driver paravirtualizzati in linux e windows (gli unici due sistemi operativi che supportano i device paravirtualizzati per i guest):
  1. kvm: adding paravirtualized device on linux guest
  2. kvm: virtio, windows and the paravirtualized network device

Nel caso in cui abbiate voluto avere una configurazione della rete col NAT avreste dovuto specificare queste righe:

    26        <interface type='network'>
    27          <mac address='52:54:00:12:34:56'/>
    28          <source network='default'/>
    29          <target dev='tap1'/>
    30          <model type='virtio'/>
    31        </interface>

In cui si usa la rete di default creata out-of-the box da libvirt, ricordatevi solo di impostare il flag net.ipv4.ip_forward a 1 nel file /etc/sysctl.conf, nel caso in cui utilizziate la rete in modalità bridged e non vogliate avere questa rete costantemente attiva potete disabilitarla tramite il comando virsh net-autostart default –disable. Per ulteriori informazioni riguardanti la configurazione della rete per qemu e kvm potete dare un’occhiata a questo mio post.

Nel caso in cui vogliate definire virtual network custum potreste trovare utili le informazioni fornite a questo indirizzo http://libvirt.org/formatnetwork.html.

  • 32-36: A questo punto definiamo un paio di periferiche di input, l’attributo type può assumere i valori mouse o tablet ed il valore dell’attributo bus può essere usb o ps2, se intendete utilizzare VNC il consiglio è di specificare un elemento input con type tablet e bus usb. Infine definiamo il tipo di grafica che vogliamo avere, in questo caso specifico indichiamo che vogliamo utilizzare VNC, nel caso in cui avessimo indicato come valore dell’elemento type sdl avremmo avuto la normale finestra SDL, su localhost con porta auto-allocata, specifichiamo il layout della tastiera tramite l’attributo keymap.

Per informazioni ancora più dettagliate riguardanti la configurazione dei domini potete dare un’occhiata alla documentazione ufficiale all’indirizzo http://libvirt.org/formatdomain.html.

Ora è necessario definire una macchina virtuale dal file xml precedentemente definito, per farlo basta digitare:

virsh define /etc/libvirt/qemu/hellgate.xml

Successivamente per editare la configurazione del guest basta digitare:

virsh edit hellgate

Utilizzo in pillole

  • Per avviare, spegnere e riavviare una macchina virtuale dovete usare i seguenti comandi. E’ necessario però che il vostro guest supporti l’ACPI visto che il comando shutdown invia il comando di spegnimento via comando ACPI al guest, il comando destroy invece è come se toglieste la corrente alla macchina reale:
 virsh start hellgate
 virsh shutdown hellgate
 virsh reboot hellgate
virsh destroy hellgate

Se preferite gestire i domini da un’interfaccia grafica potete utilizzare virt-manager. Per collegarsi al server VNC così avviato potete usare indifferentemente vncviewer, virt-viewer e virt-manager.

  • Per poter gestire le macchine virtuali tramite gli strumenti messi a disposizione da libvirt dovete aggiungere il vostro utente al gruppo di sistema libvirtd col comando:
addgroup $nome_utente_da_voi_utilizzato libvirtd
  • Per avviare una macchina virtuale all’avvio della macchina reale digitate alla console:
virsh autostart hellgate

…oppure spuntate l’apposito flag da virt-manager.

  • Per vedere l’elenco completo dei comandi che virsh vi mette a disposizione potete utilizzare virsh help.
  • Per aggiungere un cdrom o un device usb dovete digitare qualcosa di simile a quanto segue:
 virsh block-attach --type cdrom --mode readonly myguest /some/path/cdimage.iso hdc

…oppure utilizzare l’interfaccia grafica messa a disposizione da virt-manager.

Per ulteriori informazioni potete visionare il wiki del progetto all’indirizzo http://wiki.libvirt.org/page/Main_Page.

E per oggi è tutto, se avete dubbi o domande (oppure se volete proporre l’argomento di qualche prossimo post) sono a disposizione.

Related post:

Comments are closed.