LibVirt com Python

LibVirt com Python
Em uma das minhas postagens anteriores, mostrei como se pode começar com LibVirt e KVM. Essa pilha de virtualização deve não ser usada como um software de virtualização de desktop, mas pretende ser executado em servidores que oferecem maior flexibilidade, eficiência e estabilidade, em vez de facilidade de uso. Significa ser automatizado para o nº grau em vez de confiar na configuração manual. Então, vamos ver como você pode se conectar ao seu daemon libvirt e automatizar o gerenciamento e o monitoramento básicos da VM usando o Python.

A configuração e as suposições básicas

Estou usando uma instalação da LibVirt KVM em um servidor Debian. Os scripts python que eu usarei estão em execução em um python 3.7.3 Ambiente. Este artigo deve molhar os pés com as ligações Python da LibVirt, quando você está projetando seu aplicativo, você deve sempre consultar a documentação oficial que cobre uma ampla gama de casos de uso e é atualizada razoavelmente com frequência.

Vamos instalar todas as dependências necessárias para o LibVirt primeiro:

$ sudo apt install pkg-config libvirt-dev
$ pip3 install libvirt-python

São todos os pacotes que você precisa.

Os seguintes scripts e trechos são executados localmente no host da libvirt, como root, em vez de ser executado em um cliente remoto. Você pode acessar os serviços remotamente, no entanto, isso exigiria uma longa digressão para proteger a conexão entre o cliente e o servidor. Portanto, estaremos nos conectando localmente, por uma questão de simplicidade.

Estabelecendo conexão com o serviço Libvirtd

Para começar, vamos abrir um prompt de python, importar a biblioteca da LibVirt e abrir uma conexão com o Libvirt.método aberto.

raiz@deb: ~# python3
Python 3.7.3 (padrão, 15 de abril de 2019, 01:55:37)
[GCC 6.3.0 20170516] no Linux

Digite “ajuda”, “direitos autorais”, “créditos” ou “licença” para obter mais informações.

>>> Importar libvirt
>>> conn = libvirt.Open ('qemu: /// System')

A variável conn agora pode ser usada para consultar o seu daemon libvirt e faremos isso em breve. Mas primeiro, uma pequena digressão.

LibVirt pode ser usado para gerenciar uma série de diferentes virtualização e pilha de contêinerização. KVM-qemu, Xen e LXC são os mais populares. Então, quando você entra no Libvirt.Open ('qemu: /// System') LibVirt permite reunir informações sobre e gerenciar os convidados QEMU. Você também pode falar com daemon lxd ou hypervisor xen usando lxc: /// system ou xen: /// sistema respectivamente.

Da mesma forma, o método Libvirt.Open () não é o único à sua disposição. Open (Name), OpenAuth (URI, Auth, Flags) e OpenReadonly (Nome) são três chamadas diferentes, cada uma das quais retorna um objeto VirConnect e oferece um nível variável de controle sobre o host. Você pode ler mais sobre eles aqui. Por enquanto, temos Conn como um objeto da classe VirConnect. Este objeto é uma porta de entrada para fazer quase tudo, desde a configuração do próprio hipervisor até a modificação dos convidados e sua alocação de recursos.

Depois de terminar de trabalhar com o objeto, feche a conexão chamando o método de fechamento nele.

>>> Conn.fechar()

No entanto, não execute o comando acima, ainda. Porque vamos brincar com o Libvirt um pouco mais. Vamos perguntar ao nosso hipervisor alguns detalhes sobre si mesmo, como o nome do host, e o número de vcpus que ele pode oferecer às VMs convidadas no total.

>>> Conn.GethostName ()
'Deb'
>>> Conn.getMaxvcpus ('qemu')
16

Agora, precisamos entender que, com os metadados da libv. XML é como JSON apenas um pouco mais mal (e um pouco mais velho). Os dados são armazenados e apresentados como uma corda literal e o que isso significa é que, se você consultar o LibVirt e a saída dessa consulta é XML, você obterá uma saída de linha única muito longa com '\ n' presente como uma corda literal em vez de uma nova linha. A função de impressão embutida do Python pode limpá-la para a legibilidade humana

>>> Imprimir (Conn.getSysInfo ())


Dell inc.
A14
..

Listagem e monitoramento VMs

Se você estiver mantendo uma grande variedade de VMs, precisará de um método para criar centenas de VMs com configuração uniforme, que também escala corretamente de cargas de trabalho rosqueadas simples para processamento multi-core e multi-threaded. LibVirt chama as VMs convidadas (ou contêineres se você estiver usando o LXC) Domínios E você pode listar informações sobre domínios individuais, bem como configurá -los se seu objeto VirConnect tiver privilégios suficientes.

Para obter informações sobre as VMs e sua utilização de recursos, você pode usar as seguintes chamadas:

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

Isso retorna uma variedade de IDs de domínio que são apenas pequenos números inteiros para uma configuração simples. Uma maneira mais confiável de rotular suas VMs, sem ter duas VMs (digamos em nós diferentes) com o mesmo ID ou nome, é usar uuids. No Libvirt, tudo pode ter um UUID, que é gerado aleatoriamente com número de 128 bits. As chances de você criar dois uuid idênticas são muito pequenas.

A rede para suas máquinas virtuais, as próprias VMs e até os pools e volumes de armazenamento têm seus Uuids individuais. Faça o uso liberal deles no seu código Python, em vez de confiar em nomes designados humanos. Infelizmente, a maneira de obter os uuids dos domínios é um pouco confusa na implementação atual desta biblioteca, na minha opinião. Exige que você forneça o ID da VM (o ID do domínio), eis como está.

domainids = Conn.listdomainsid ()
para domainid em domainids:
domain = Conn.LookUpById ()
uuid = domínio.Uuidstring ()
Imprimir (uuid)

Agora você pode ver a lista de uuids de domínio. Também tropeçamos em um novo objeto Python Libvirt.Virdomain, que, tem seu próprio conjunto de métodos associados a ele como a variável conn, que era uma libirt.objeto VirConnect e tinha métodos como listdomainsid () e LookUpById () associados a ele.

Para ambos os métodos, você pode usar os métodos de DIR () embutidos do Python para que os objetos possam listar suas variáveis ​​e métodos internos.

Por exemplo:

>>> dir (Conn)
['_… GS', 'SchedulerType', 'Screenshot', 'SecurityLabel', 'SecurityLabelList',
'SendKey', 'SendprocessSignal', 'Sesautostart', 'Setblkioparameters', 'SetBlockioTune',
'setGuestvcpus', 'setInterfaceParameters', 'setMaxMemory', 'SetMemory', 'SetMemoryFlags',
'SetMemoryParameters', 'SetMemoryStatsPeriod', 'SetMetadata', 'Setnumaparameters',
'SetPerfevents', 'SetSchedulerParameters', 'SetSchedulerParametersflags', 'Settime',
'Setuse'…]

Isso pode realmente ajudá -lo a se lembrar rapidamente do nome exato de um método e do objeto com o qual deve ser usado. Agora que temos um LibVirt.Objeto Virdomain, vamos usá -lo para listar vários detalhes sobre esta VM em execução.

>>> domínio.info ()

Isso fornece as informações sobre o estado da VM, a memória máxima e os núcleos da CPU, como mostrado aqui.

Você também pode encontrar outras informações sobre a VM usando métodos diferentes como ostype ()

>>> domínio.Ostype ()
'hvm'

Há muita flexibilidade quando se trata da API que a LibVirt expõe e você só precisa se preocupar com o seu caso de uso e sem se preocupar com a enorme complexidade que a LibVirt lida.

Conclusão

Em minhas viagens à tecnologia Libvirt, a ausência de Uuids como cidadão de primeira classe foi provavelmente o único ponto de dor que eu enfrentei, que parecia uma má escolha de design. Fora isso, Libvirt é bastante bacana para o que realiza. Sim, há muitas outras coisas que poderiam ter sido feitas de uma maneira melhor, mas esse é sempre o caso do software. Em retrospectiva, as más decisões são sempre óbvias, mas o custo de reescrever um software, tão difundido quanto Libvirt, é muitas vezes tremendo.

Muito foi construído sobre ele, pois o projeto evoluiu lenta e firmemente.

Em vez de tentar aprender a biblioteca inteira de uma só vez, eu recomendaria inventar um pequeno projeto ou uma ideia e implementar isso usando o Python e o Libvirt. A documentação é bastante extensa, com muitos exemplos e realmente obriga a pensar no design adequado de software e na pilha de virtualização ao mesmo tempo.