Recuperar informações de porta serial de um domínio libvirt?

5

Estou tentando recuperar as informações da porta serial, também conhecida como Source Path de um domínio libvirt (usando a máquina qemu / KVM):

Serial Device 1 (Primary Console)
  Device type: pty
  Source path: /dev/pts/2

Mas verifiquei a referência da API aqui e parece não suportar Source Path .

Existe algum comando como VBoxManage que possa listar essas informações diretamente?

Estranho, estou no grupo libvirt , posso controlar (iniciar, parar, etc.) a máquina KVM com virt-manager , virsh também mostra um prompt virsh # .

Mas não consigo ver nada com o comando virsh list --all , ainda tenho que executá-lo com privilégios de root.

    
por daisy 05.07.2014 / 06:53

1 resposta

8

O KVM é uma API do kernel para virtualização. Não lida com portas seriais . qemu é um emulador de máquina (PC e outros) que pode usar kvm para melhorar o desempenho da virtualização. Ele pode emular uma porta serial padrão UART 8250 ( isa-serial ) ou uma porta serial paravirtualizada ( virtio-serial ).

No qemu, você define sua máquina com argumentos de linha de comando que especificam qual dispositivo incluir em sua máquina e o que backend esses dispositivos mapeiam (por exemplo, disco rígido emulado para um arquivo de imagem, rede adaptadores para um tap device ...).

Para portas seriais, você normalmente mapeia isso para o que o qemu chama chardevs .

Há muitos possíveis diferentes, normalmente qualquer coisa que possa enviar e receber bytes, como pipes, soquetes, descritores de arquivos, pseudo-terminais.

Por exemplo, se você executar o qemu como:

qemu ... -device isa-serial,chardev=c,id=s -chardev pty,id=c 

qemu aloca um pseudo-terminal, relata isso no stdout na inicialização:

char device redirected to /dev/pts/18 (label c)

e mapeia isso para uma nova porta serial isa adicionada à VM. Se inicializar uma VM Linux, você verá nos logs do kernel:

[    3.636092] Serial: 8250/16550 driver, 32 ports, IRQ sharing enabled
[    3.658666] 00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A

E se você escrever algo para /dev/ttyS0 no convidado, poderá lê-lo em /dev/pts/18 no host.

Depois que um qemu VM é iniciado, você pode controlá-lo com o que o qemu chama de monitor interfaces. Existem dois tipos de interfaces monitor :

  • Monitor humano: um CLI semelhante a shell
  • Monitor de máquina: uma interface mais amigável à máquina que implementa um protocolo de texto (json) chamado qemu machine protocol (QMP).

Se você não especificar nada e usar o console SDL padrão, você receberá um monitor humano no console SDL pressionando Ctrl + Alt + 2 . p>

Mas você também pode especificar qualquer backend chardev (pty, socket, stdio ...) para isso. Normalmente, eu uso stdio lá:

qemu ... -monitor stdio

Para obter o monitor no terminal, inicio o qemu ao executar o qemu para testes.

Na interface monitor , você pode executar o comando info qtree para obter informações sobre os dispositivos da sua máquina:

(qemu) info qtree
bus: main-system-bus
[...]
  dev: i440FX-pcihost, id ""
[...]
bus: pci.0
[...]
  dev: PIIX3, id ""
    class ISA bridge, addr 00:01.0, pci id 8086:7000 (sub 1af4:1100)
    bus: isa.0
      type ISA
      dev: isa-serial, id "s"
    index = 0 (0)
    iobase = 1016 (0x3f8)
    irq = 4 (0x4)
    chardev = "c"

Acima, você vê o dispositivo isa-serial que criei anteriormente e mapeia para o "c" chardev .

Você pode obter informações desse chardev usando info chardev :

(qemu) info chardev
parallel0: filename=vc
c: filename=pty:/dev/pts/18
compat_monitor0: filename=stdio

Você vê c maps no /dev/pts/18 pty .

Você pode obter as mesmas informações programaticamente com um monitor QMP. Se você iniciar sua VM com -qmp stdio , poderá passar os comandos para lá:

{"execute":"qmp_capabilities"} # enable commands
{"return": {}}   # return value

{"execute":"qom-list","arguments":{"path":"/machine/peripheral/s"}}
{"return": [{"name": "parent_bus", "type": "link<bus>"}, {"name": "wakeup", "type": "uint32"}, {"name": "chardev", "type": "str"}, {"name": "irq", "type": "uint32"}, {"name": "iobase", "type": "uint32"}, {"name": "index", "type": "uint32"}, {"name": "hotpluggable", "type": "bool"}, {"name": "realized", "type": "bool"}, {"name": "type", "type": "string"}]}

# query chardev for "s":
{"execute":"qom-get","arguments":{"path":"/machine/peripheral/s","property":"chardev"}}
{"return": "c"}

# query chardevs:
{"execute":"query-chardev"}
{"return": [{"filename": "vc", "label": "parallel0"}, {"filename": "pty:/dev/pts/18", "label": "c"}, {"filename": "stdio", "label": "compat_monitor0"}]}

(veja como os qom-list e qom-get (qom que representam o modelo de objeto do qemu) fazem reminiscência de fazer ls e cat in /sys na máquina Linux).

Agora, sua pergunta sugere que você não está chamando o qemu diretamente à mão, mas usando libvirt . libvirt é uma das muitas infraestruturas de gerenciamento de virtualização. Pode gerenciar VMs do qemu (com ou sem kvm), xen ou virtualbox (pelo menos).

Para VMs do qemu, quando você define uma VM em libvirt (com virt-manager ou outro), isso se traduz em argumentos a serem passados para um comando qemu, e o libvirt normalmente usa um monitor qmp para controlar uma VM após foi iniciado.

Para um domínio libvirt , você pode obter a configuração atual de um domínio com:

virsh dumpxml the-domain

Que despeja a configuração como XML. Você pode extrair informações usando xmllint ou xmlstarlet ou qualquer solução de análise XML de sua escolha.

$ virsh dumpxml domain | xmllint --xpath '//serial' -
<serial type="pty">
  <source path="/dev/pts/4"/>
  <target port="0"/>
  <alias name="serial0"/>
</serial><serial type="pty">
  <source path="/dev/pts/5"/>
  <target port="1"/>
  <alias name="serial1"/>
</serial><serial type="pty">
  <source path="/dev/pts/6"/>
  <target port="2"/>
  <alias name="serial2"/>
</serial>
$ virsh dumpxml domain |
  xmllint --xpath 'string(//serial[target/@port=0]/source/@path)' -
/dev/pts/4

Os equivalentes com xmlstarlet :

sudo virsh dumpxml domain | xmlstarlet sel -t -c '//serial'
sudo virsh dumpxml domain |
  xmlstarlet sel -t -v '//serial[target/@port=0]/source/@path'

Note que você também pode passar comandos para o monitor QMP com o comando virsh qemu-monitor-command .

Por exemplo:

$ virsh qemu-monitor-command domain '{"execute":"qom-get","arguments":
{"path":"/machine/peripheral/serial0","property":"chardev"}}'
{"return":"charserial0","id":"libvirt-84"}
    
por 05.07.2014 / 19:16

Tags