Libvirt con Python

Libvirt con Python
In uno dei miei post precedenti, ho mostrato come si può iniziare con Libvirt e KVM. Questo stack di virtualizzazione non intende essere utilizzato come software di virtualizzazione desktop, piuttosto è pensato per essere eseguito su server che offrono maggiore flessibilità, efficienza e stabilità, anziché facilità d'uso. Si intende essere automatizzato per nth laurea piuttosto che fare affidamento sulla configurazione manuale. Quindi vediamo come puoi connetterti al tuo demone Libvirt e automatizzare la gestione e il monitoraggio di base della VM utilizzando Python.

Le ipotesi di configurazione e di base

Sto usando un'installazione di Libvirt KVM su un server Debian. Gli script di Python che userò sono in esecuzione in un Python 3.7.3 ambiente. Questo articolo dovrebbe far bagnare i piedi con i binding Python di Libvirt, quando stai progettando la tua applicazione dovresti sempre fare riferimento alla documentazione ufficiale che copre una vasta gamma di casi d'uso e vengono aggiornati ragionevolmente.

Installiamo prima tutte le dipendenze richieste per Libvirt:

$ sudo apt Installa pkg-config libvirt-dev
$ PIP3 Installa Libvirt-Python

Sono tutti i pacchetti di cui hai bisogno.

Vengono eseguiti i seguenti script e frammenti a livello locale Sull'host Libvirt, come root, piuttosto che essere eseguiti su un client remoto. È possibile accedere ai servizi in remoto, tuttavia, che richiederebbe una lunga digressione per proteggere la connessione tra il client e il server. Pertanto, ci connetteremo localmente, per motivi di semplicità.

Stabilire connessione con il servizio libvirtd

Per iniziare, apriamo un prompt Python, importa la libreria Libvirt e apriamo una connessione con Libvirt.Metodo aperto.

root@deb: ~# python3
Python 3.7.3 (impostazione predefinita, 15 aprile 2019, 01:55:37)
[GCC 6.3.0 20170516] su Linux

Digita "Guida", "Copyright", "Credit" o "Licenza" per ulteriori informazioni.

>>> Importa libvirt
>>> conn = libvirt.open ('qemu: /// system')

La variabile Conn può ora essere usata per interrogare il demone Libvirt e lo faremo a breve. Ma prima, un po 'di digressione.

Libvirt può essere utilizzato per gestire una serie di diversi stack di virtualizzazione e containerizzazione. KVM-QEMU, XEN e LXC sono i più popolari di questi. Quindi quando entri Libvirt.Open ('Qemu: /// System') Libvirt ti consente di raccogliere informazioni e gestire gli ospiti QEMU. Puoi anche parlare con LXD Daemon o Xen Hypervisor usando rispettivamente LXC: /// System o Xen: ///.

Allo stesso modo, il metodo libvirt.Open () non è l'unico a tua disposizione. Open (Nome), OpenAuth (Uri, Auth, Flags) e OpenReadonly (nome) sono tre diverse chiamate ciascuna delle quali restituisce un oggetto VirConnect e offre un livello di controllo variabile sull'host. Puoi leggere di più su di loro qui. Per ora, abbiamo Conn come oggetto della classe VirConnect. Questo oggetto è un gateway per fare quasi qualsiasi cosa dalla configurazione dell'hypervisor stesso alla modifica degli ospiti e alla loro allocazione delle risorse.

Una volta che hai finito di lavorare con l'oggetto, assicurati di chiudere la connessione chiamando il metodo di chiusura su di esso.

>>> Conn.vicino()

Tuttavia, non eseguire ancora il comando sopra. Perché suoneremo un po 'di più con Libvirt. Chiediamo al nostro hypervisor alcuni dettagli su se stesso, come il nome host, e il numero di VCPU che può offrire alle macchine virtuali ospiti in totale.

>>> Conn.gethostname ()
'Deb'
>>> Conn.getMaxvcpus ('QEMU')
16

Ora, dobbiamo capire che con i metadati libvirt su oggetti come statistiche hypervisor, VMS, le loro informazioni di rete e archiviazione, ecc. Sono tutti rappresentati in formato XML. XML è una specie come Json solo un po 'Clumsier (e un po' più vecchio). I dati vengono archiviati e presentati come una stringa letterale e ciò che significa è che se si esegue la domanda di libvirt e l'output di quella query è XML otterrai un output a linea singola davvero lungo con '\ n' presente come una stringa letterale piuttosto che nuova linea. La funzione di stampa integrata di Python può ripulirla per la leggibilità umana

>>> stampa (Conn.getSysinfo ())


Dell Inc.
A14
..

Elenco e monitoraggio VMS

Se stai mantenendo una vasta gamma di VM, è necessario un metodo per creare centinaia di VM con configurazione uniforme che si adattano correttamente anche da semplici carichi di lavoro a thread singolo a elaborazione multi-core e multi-thread. Libvirt chiama le macchine virtuali degli ospiti (o contenitori se si utilizza LXC) Domini E puoi elencare informazioni sui singoli domini e configurarli se il tuo oggetto VirConnect ha privilegi sufficienti.

Per ottenere informazioni sulle VM e sul loro utilizzo delle risorse è possibile utilizzare le seguenti chiamate:

>>> Conn.listDomainSId ()
[4, 5]

Questo restituisce una serie di ID di dominio che sono solo piccoli numeri interi per una semplice configurazione di libvirt. Un modo più affidabile per etichettare le VM, senza avere due VM (diciamo su nodi diversi) con lo stesso ID o nome, è usare gli uuidi. In libvirt tutto può avere un uuid, che viene generato in modo casuale a 128 bit. Le possibilità che tu crei due uuidi identici sono davvero piuttosto piccoli.

La rete per le tue macchine virtuali, le macchine virtuali stesse e persino i pool di archiviazione e i volumi hanno i loro singoli uuidi. Fai un uso liberale di loro nel tuo codice Python, invece di fare affidamento sui nomi assegnati umani. Sfortunatamente, il modo per ottenere gli uuidi dei domini è un po 'disordinato nell'attuale implementazione di questa biblioteca, secondo me. Richiede di fornire l'ID della VM (l'ID del dominio), ecco come sembra.

Domainids = Conn.listDomainSId ()
Per Domainid nei domini:
Dominio = Conn.LookUpById ()
uuid = dominio.Uuidstring ()
Stampa (uuid)

Ora puoi vedere l'elenco degli uuidi del dominio. Ci siamo anche imbattuti in un nuovo oggetto Python Libvirt.Virdomain, che ha il proprio set di metodi ad essa associati in modo molto simile alla variabile Conn che era una libvirt.oggetto VirConnect e avevano metodi come ListDomainSId () e LookUpById () ad esso associati.

Per entrambi questi metodi è possibile utilizzare i metodi di Dir () integrati di Python in modo che gli oggetti possano elencare le loro variabili e metodi interni.

Per esempio:

>>> Dir (Conn)
['_… GS', 'SchedulerType', 'Screenshot', 'SecurityLabel', 'SecurityLabellist',
"Sendkey", "SendProcessSignal", "setautostart", "setblkioparameters", "setblockiotune",
'setGestvcpus', 'setInterfaceParameters', 'setMaxMemory', 'setmemory', 'setmemoryflags',
'setmemoryparameters', 'setmemorystatsperiod', 'setmetadata', 'setnumaparameters',
'setperfevents', 'setschedulerparameters', 'setschedulerparametersflags', 'settime',
'setus'…]

Questo può davvero aiutarti a ricordare rapidamente il nome esatto di un metodo e l'oggetto con cui dovrebbe essere usato. Ora che abbiamo un libvirt.Oggetto Virdomain, usiamolo per elencare vari dettagli su questa VM in esecuzione.

>>> dominio.informazioni()

Questo ti dà le informazioni relative allo stato della VM, alla massima memoria e ai core della CPU come mostrato qui.

Puoi anche trovare altre informazioni sulla VM utilizzando metodi diversi come Ostype ()

>>> dominio.Ostype ()
'hvm'

C'è molta flessibilità quando si tratta dell'API che espone libvirt e devi solo preoccuparti del tuo caso d'uso e senza preoccuparti dell'enorme complessità che Libvirt gestisce.

Conclusione

Nei miei viaggi nella tecnologia Libvirt, l'assenza di uuidi come cittadino di prima classe era probabilmente l'unico punto dolore che ho dovuto affrontare, il che sembrava una cattiva scelta di design. A parte questo, Libvirt è piuttosto elegante per ciò che realizza. Sì, ci sono molte altre cose che avrebbero potuto essere fatte in modo migliore, ma questo è sempre il caso del software. Con il senno di poi, le cattive decisioni sono sempre ovvie, ma il costo di riscrivere un software, diffuso come Libvirt, è spesso eccezionale.

Molto è stato costruito su di esso, mentre il progetto si è evoluto lentamente e costantemente.

Invece di provare a imparare l'intera biblioteca in una volta, consiglierei di elaborare un piccolo progetto o un'idea e implementare che usando Python e Libvirt. La documentazione è piuttosto estesa con molti esempi e ti costringe davvero a pensare allo stack di progettazione e virtualizzazione corretta e virtualizzazione allo stesso tempo.