KVM
virtualizacion
Algunos conceptos:
1. Entrar en la BIOS del sistema y asegurarse de que el soporte de virtualización está activado
2. Instalar un sistema GNU/Linux reciente (yo pruebo con Debian 6.x=
3. Comprobar que el sistema operativo soporta virtualizacion:
Una vez encontré un escenario en el que la prueba 3.1. era KO y la 3.2. OK, por lo que creo que la más exacta es la 3.1.
3.1. Ver si kvm está deshabilitado a nivel de BIOS
dmesg | grep bios
3.2 Ejecutar
sudo egrep '(vmx|svm)' --color=always /proc/cpuinfo
En caso de que SI soporte virtualizacion veremos lo siguiente:
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority
Con la palabra 'vmx' o 'svm' en rojo
4. Instalar los siguientes paquetes:
sudo aptitude install qemu-kvm libvirt-bin virtinst qemu-utils
Nota: qemu-utils es necesario para exportar de discos raw a qcow2
5. Anyadir el usuario X al grupo:
sudo adduser USUARIO libvirt
6. Comprobar que el demonio libvirtd esta corriendo (necesario para poder administrar KVM desde un entorno grafico con virt-manager):
ps ax | grep libvirt 4149 ? Sl 0:00 /usr/sbin/libvirtd -d
La principal diferencia es VNC. Configuracion:
<domain type='kvm'> <name>test-1.dev.jj.com</name> <uuid>12b440aa-fee3-b6cc-31d1-4d2bde56e0df</uuid> <memory>1048576</memory> <currentMemory>524288</currentMemory> <vcpu>2</vcpu> <os> <type arch='x86_64' machine='pc-0.12'>hvm</type> <boot dev='hd'/> </os> <features> <acpi/> <apic/> <pae/> </features> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> <emulator>/usr/bin/kvm</emulator> <disk type='file' device='disk'> <driver name='qemu' type='raw'/> <source file='/var/lib/libvirt/images/test-1.dev.jj.com.img'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </disk> <disk type='block' device='cdrom'> <driver name='qemu' type='raw'/> <target dev='hdc' bus='ide'/> <readonly/> <address type='drive' controller='0' bus='1' unit='0'/> </disk> <controller type='ide' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> </controller> <interface type='network'> <mac address='52:54:00:2a:b7:e1'/> <source network='default'/> <target dev='vnet0'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface> <serial type='pty'> <target port='0'/> </serial> <console type='pty'> <target type='serial' port='0'/> </console> <input type='tablet' bus='usb'/> <input type='mouse' bus='ps2'/> <graphics type='vnc' port='-1' autoport='yes'/> <video> <model type='cirrus' vram='9216' heads='1'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </video> <memballoon model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </memballoon> </devices> </domain>
Lanzar los comandos desde el hipervisor.
Debian estable desde red configurada con NAT, 1024B de RAM, y disco duro con algunas configuraciones para mejor rendimiento:
sudo virt-install \ -n template-1.dev.local.legido.com \ -r 1024 \ --vcpus=2 \ --os-variant=debianwheezy \ --disk /var/lib/libvirt/images/template-1.dev.local.legido.com,size=5,bus=virtio,cache=none,format=qcow2 \ --nographics \ --network network=default \ -l http://ftp.debian.org/debian/dists/wheezy/main/installer-amd64/ \ -x console=ttyS0,115200
Debian estable desde red configurada con bridge, 512MB de RAM y 2 GB de disco duro:
virt-install \ -n vm1 \ -r 512 \ --vcpus=2 \ --os-variant=debiansqueeze \ --disk /var/lib/libvirt/images/vm1.img,size=2 \ --nographics \ --bridge br0 \ -l http://ftp.debian.org/debian/dists/squeeze/main/installer-amd64/ \ -x console=ttyS0,115200
Ubuntu server, NAT conectado a red “default”:
sudo virt-install \ -n template-2.dev.local.jamgo.org \ -r 512 \ --vcpus=2 \ --os-variant=ubuntuquantal \ --disk /var/lib/libvirt/images/template-2.dev.local.jamgo.org.qcow2,size=8,bus=virtio,cache=none \ --nographics \ --network network=default \ -l http://archive.ubuntu.com/ubuntu/dists/quantal/main/installer-amd64/ \ -x console=ttyS0,115200
Debian Jessie desde CD:
sudo virt-install \ -n template-1.dev.local.legido.com \ -r 512 \ --vcpus=2 \ --os-variant=debianwheezy \ --disk pool=template_1,sparse=false,size=8,cache=none,format=raw,bus=virtio \ --graphics vnc \ --bridge virbr0 \ --cdrom=/var/lib/libvirt/images/debian-jessie-amd64-netinst.iso
vmbuilder
http://www.howtoforge.com/virtualization-with-kvm-on-a-debian-squeeze-server
TODO Crear una VM desde linea de comandos con un VL como storage
Escenario: NO quiero instalar las X en el hipervisor, y quiero administrar gráficamente el hipervisor y las máquinas virtuales desde otra máquina (cliente) con las X instaladas
1. (Hipervisor) Instalar los siguientes paquetes:
sudo aptitude update; sudo aptitude install netcat socat -R
2. (Hipervisor) Crear el siguiente archivo:
sudo vim /bin/netcatsocket
Con el siguiente contenido:
#!/bin/bash socat - unix-client:$2
3. (Hipervisor) Darle permisos
sudo chmod +x /bin/netcatsocket
4. (Cliente) Instalar paquetes:
sudo aptitude update; sudo aptitude install virt-manager ssh-askpass -R
5. (Cliente) Conectarse al hipervisor:
virt-manager -c qemu+ssh://USUARIO@HIPERVISOR:PUERTO/system?netcat=netcatsocket
1. (VM) Editar
sudo vim /etc/inittab
Y anyadir:
T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
2. (VM) Editar
sudo vim /etc/default/grub
Y dejar la linea tal que asi:
GRUB_CMDLINE_LINUX="console=tty0"
3. (VM) Recargar grub:
sudo update-grub
4. (Hipervisor) Conectarse a la consla de la VM:
sudo virsh console template Connected to domain template Escape character is ^]
Toca un tecla (por ejemplo enter) y aparecera el prompt:
Debian GNU/Linux 6.0 template ttyS0 template login:
5. Para finalizar la conexion CTRL + ]
* Listar todas las Maquinas Virtuales (VM):
virsh list --all Id Name State ---------------------------------------------------- - name shut off
* Forzar apagado VM:
sudo virsh destroy vm2
* Eliminar por completo una VM:
virsh undefine vm2 Domain vm2 has been undefined
* Cambiar la memoria maxima. IMPORTANTE: requiere apagar la VM, mejor apagarla primero a traves del Sistema Operativo:
sudo virsh shutdown vm2 sudo virsh setmaxmem vm2 524288 sudo virsh start vm2 sudo virsh setmem vm2 524288
En este ejemplo se establece el valor en 524288 KB
sudo virsh autostart myvmname
* virt-manager
CTRL + ALT + F7
o
CTRL + ALT
* Cannot recv data: Host key verification failed. : Connection reset by peer
Sucede al lanzar:
virt-manager -c qemu+ssh://usuario@hipervisor/system
Solucion: iniciar una sesion SSH para almacenar las claves del hipervisor en el cliente:
ssh usuario@hipervisor
* Error starting network 'default': internal error
Suce al intentar activar o crear una nueva red virtual desde virt-manager debido a un bug de libvirt.
Solucion: actualizar los paquetes relacionados con libvirt
1. Editar:
sudo vim /etc/apt/sources.list
Y anyadir la siguiente linea:
deb http://backports.debian.org/debian-backports squeeze-backports main
2. Actualizar la cache de paquetes:
sudo aptitude update
3. Instalar la version de backports de los siguientes paquetes:
sudo aptitude -t squeeze-backports install libvirt-bin libvirt0 python-libvirt dnsmasq-base -R
4. Reiniciar el demonio libvirtd:
sudo /etc/init.d/libvirt-bin restart
Queremos renombrar de “test-2.example.com” a “test-1.example.com”. Solo existe la primera, “test-2.example.com”
1. Volcar la configuración:
sudo su - cd /etc/libvirt/qemu/ virsh dumpxml test-2.example.com.xml > test-1.example.com.xml
2. Apagar la VM si no lo está (a nivel de Sistema Operativo mejor).
Asegurarse de que NO tiene snapshot
3. Cepillarse la VM:
virsh undefine test-2.example.com
4. Editar el archivo de configuracion de la nueva VM:
sudo vim test-1.example.com.xml
Y asegurarse de que los siguientes valores son unicos y correctos:
<name>test-1.example.com</name>
<source dev='/dev/vg/lv_test_1'/>
<mac address='00:16:3e:0e:3e:53'/>
Script para generar MAC addresses:
#!/usr/bin/python # macgen.py script to generate a MAC address for guests on Xen # import random # def randomMAC(): mac = [ 0x00, 0x16, 0x3e, random.randint(0x00, 0x7f), random.randint(0x00, 0xff), random.randint(0x00, 0xff) ] return ':'.join(map(lambda x: "%02x" % x, mac)) # print randomMAC()
Ahora obtenemos el listado de VMS:
virsh list --all
Y para cada una de ellas obtenemos la MAC address:
virsh dumpxml vm-1.example.com | grep "mac address" | awk '{print $2}' | cut -d "'" -f2
TODO: hacer un script en bash que lo haga
Finalmente nos aseguramos que la nueva MAC generada es unica.
5. Definir la nueva VM:
virsh define test-1.example.com.xml
1. Para VM destino
2. Eliminarla:
sudo virsh undefine test-1.example.com
Seguir los pasos de vm_destino_no_existe
1. Dejar la imagen iso en el hipervisor:
/var/lib/libvirt/images/systemrescuecd-x86-3.4.2.iso
2. Editar la VM:
sudo virsh edit vm_1
2.1. Anyadir el siguiente bloque dentro del bloque <devices>:
<devices> ... <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <source file='/var/lib/libvirt/images/systemrescuecd-x86-3.4.2.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> ... </devices>
Al grabar libvirt le asignara una entrada con la direccion PCI dentro del bloque <disk>
2.2. (Opcional) Si se quiere arrancar desde CD anyadir el siguiente bloque dentro del bloque <os>:
<os> <boot dev='cdrom'/> <boot dev='hd'/> </os>
2.3. Grabar y salir
1. Editar la VM desde virsh:
sudo virsh edit vm_1
1.1. Anyadir el siguiente bloque dentro del bloque <devices>:
<devices> ... <input type='mouse' bus='ps2'/> <graphics type='vnc' port='-1' autoport='yes'/> <video> <model type='cirrus' vram='9216' heads='1'/> </video> ... </devices>
Al grabar libvirt le asignara una entrada con la direccion PCI dentro del bloque <disk>
1.2. Grabar y salir
NOTA estas instrucciones sirven tambien cuando el almacenamiento de la VM se hace en un LV del host. Solo hay que cambiar el paso 2
La estrategia es extender el disco, crear una nueva particion en el nuevo espacio, crear un PV, anyadirlo al VG, extender el LV y redimensionar el sistema de archivos (EXT4…).
1. Para la VM, a ser posible desde el Sistema Operativo:
ssh test7 sudo shutdown -h now
2. Extender el disco:
sudo qemu-img resize /var/lib/libvirt/images/test7.qcow2 +8G Image resized.
NOTA KVM todavia no muestra el nuevo tamano si hacemos 'ls -lath /var/lib/libvirt/images/test7.qcow2'
3. Arrancar la nueva VM:
sudo virsh start test7 Domain test7 started
4. Comprobar que el Sistema Operativa ve el nuevo espacio (10 GB):
ssh test7 sudo fdisk -l
Disk /dev/vda: 10.7 GB, 10737418240 bytes 16 heads, 63 sectors/track, 20805 cylinders Units = cylinders of 1008 * 512 = 516096 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00031f27 Device Boot Start End Blocks Id System /dev/vda1 * 3 496 248832 83 Linux Partition 1 does not end on cylinder boundary. /dev/vda2 498 4159 1845249 5 Extended Partition 2 does not end on cylinder boundary. /dev/vda5 498 4159 1845248 8e Linux LVM Disk /dev/dm-0: 1753 MB, 1753219072 bytes 255 heads, 63 sectors/track, 213 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00000000 Disk /dev/dm-0 doesn't contain a valid partition table Disk /dev/dm-1: 134 MB, 134217728 bytes 255 heads, 63 sectors/track, 16 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00000000 Disk /dev/dm-1 doesn't contain a valid partition table
NOTA Los mensajes “Partition 1 does not end on cylinder boundary.” son ajenos a esta receta, pero deben evitarse con un correcto particionamiento.
5. Crear una nueva particion
sudo fdisk /dev/vda
n p [enter] (en mi caso particion 3)
Aqui introducir el sector final de la partición anterior más 1, o el siguiente numero que sea divisible por 8 si el host tiene un tamanyo fisico de sector de 4096 bytes. Luego aceptar el valor propuesto (el último sector del disco menos 1)
w
6. Aqui hay que reiniciar para que la particion sea usable por el Sistema Operativo:
sudo shutdown -r now
7. Crear un PV con la nueva particion:
sudo pvcreate /dev/vda3 Physical volume "/dev/vda3" successfully created
8. Anyadir ese PV al VG. Primero obtener el nombre del VG y del PV:
sudo vgscan
Reading all physical volumes. This may take a while... Found volume group "template" using metadata type lvm2
sudo pvscan
PV /dev/vda5 VG template lvm2 [1.76 GiB / 0 free] PV /dev/vda3 lvm2 [8.00 GiB] Total: 2 [9.76 GiB] / in use: 1 [1.76 GiB] / in no VG: 1 [8.00 GiB]
Anyadimos el PV '/dev/vda3' al VG 'template':
sudo vgextend template /dev/vda3 Volume group "template" successfully extended
9. Extendemos el VL. Primero los listamos:
sudo lvscan
ACTIVE '/dev/template/root' [1.63 GiB] inherit ACTIVE '/dev/template/swap_1' [128.00 MiB] inherit
Vamos a extender el LV '/dev/template/root' todo lo que podamos:
sudo lvextend -l +100%FREE /dev/template/root Extending logical volume root to 9.63 GiB Logical volume root successfully resized
10. Extendemos el sistema de archivos. El proceso tarda 1 minuto para 8GB:
sudo resize2fs /dev/mapper/template-root
resize2fs 1.41.12 (17-May-2010) Filesystem at /dev/mapper/template-root is mounted on /; on-line resizing required old desc_blocks = 1, new_desc_blocks = 1 Performing an on-line resize of /dev/mapper/template-root to 2525184 (4k) blocks. The filesystem on /dev/mapper/template-root is now 2525184 blocks long.
Comprobamos que todo ha ido bien:
df -h
Filesystem Size Used Avail Use% Mounted on /dev/mapper/template-root 9.5G 565M 8.5G 7% / tmpfs 249M 0 249M 0% /lib/init/rw udev 244M 108K 244M 1% /dev tmpfs 249M 0 249M 0% /dev/shm /dev/vda1 228M 16M 201M 8% /boot
Todas las operaciones se realizan desde el hipervisor. Este procedimiento es útil si por ejemplo queremos cambiar una contraseña que se nos ha olvidado.
1. Cargar módulo del kernel
sudo modprobe nbd max_part=63
2. Montar disco qcow2:
sudo qemu-nbd -c /dev/nbd0 /ruta/disco/vm_1.qcow2 sudo mkdir /mnt/vm_1 sudo mount /dev/nbd0p1 /mnt/vm_1
3. Si la VM tiene LVM:
3.1 (Opcional) Instalar LVM
sudo aptitude install lvm2 -R
3.2 Buscar Volume Group:
vgscan Reading all physical volumes. This may take a while... Found volume group "template-1" using metadata type lvm2
Encuentro el VG 'template-1'.
3.3 Activar Volume Group:
vgchange -ay 2 logical volume(s) in volume group "template-1" now active
3.4 Listar Logical Volumes:
lvdisplay --- Logical volume --- LV Path /dev/template-1/root LV Name root VG Name template-1 LV UUID Tvzd3L-24mZ-DJtf-3Rno-Inxv-r8et-fOAvpR LV Write Access read/write LV Creation host, time template-1, 2013-04-05 10:21:48 +0200 LV Status available # open 0 LV Size 7.23 GiB Current LE 1851 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 252:0 --- Logical volume --- LV Path /dev/template-1/swap_1 LV Name swap_1 VG Name template-1 LV UUID 4EY2TJ-Jcow-PFis-1VRJ-IWyE-NGwB-lSbNmd LV Write Access read/write LV Creation host, time template-1, 2013-04-05 10:21:48 +0200 LV Status available # open 0 LV Size 508.00 MiB Current LE 127 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 252:1
En este caso me interesa el VL 'root', con el path '/dev/template-1/root'
3.5 Montar el LV deseado, en este caso “/”:
sudo mkdir /mnt/vm_1_root sudo mount /dev/template-1/root /mnt/vm_1_root
3.6 Entrar en esa particion:
sudo chroot /mnt/vm_1_root
3.7 Cambiar la contrasenya o realizar la operacion que se quiera:
passwd root
3.8 Salir
exit
4. Desmontar todo:
umount /mnt/vm_1_root vgchange -an VolGroupName umount /mnt/vm_1 killall qemu-nbd
Comprobar con “ps ax” si el proceso “qemu-nbd” ha finalizado
Acronimos:
| LVM | Logical Volume Manager | | PV | Physical Volume | | VG | Volume Group | | LV | Logical Volume |
Device Boot Start End Blocks Id System /dev/mapper/vg-lv_test_2p1 * 2048 499711 248832 83 Linux /dev/mapper/vg-lv_test_2p2 501758 10483711 4990977 5 Extended Partition 2 does not start on physical sector boundary. /dev/mapper/vg-lv_test_2p5 501760 10483711 4990976 8e Linux LVM
1. Determinar el tamanyo del LV de origen:
sudo lvs | grep test_2
2. Crear un LV de backup con el mismo tamanyo:
sudo lvcreate vg --name lv_test_2_clone --size=8G
3. Determinar el Path del nuevo LV:
sudo lvdisplay | grep Path | grep test_2_clone
4. Determinar el Path del LV origen:
sudo lvdisplay | grep Path | grep test_2
5. Apagar la VM (mejor desde dentro de la propia VM)
6. Copiar bit a bit el LV. El Path origen se toma del paso 4 y el destino del paso 3:
time sudo dd if=/dev/vg/lv_test_2 of=/dev/vg/lv_test_2_clone bs=4096
La velocidad ronda los 60 MB/s
7. Editar la VM y anyadirle:
sudo virsh edit test_2
Ejemplo de los bloques a anyadir en el XML de la VM (ajustar por ejemplo el nombre del disco 2, etc…):
<os> <boot dev='cdrom'/> ... </os> <devices> ... <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <source file='/var/lib/libvirt/images/systemrescuecd-x86-3.4.2.iso'/> <target dev='hdc' bus='ide'/> <readonly/> </disk> <disk type='block' device='disk'> <driver name='qemu' type='raw' cache='none'/> <source dev='/dev/vg/lv_test_2_clone'/> <target dev='vdb' bus='virtio'/> </disk> ... <input type='mouse' bus='ps2'/> <graphics type='vnc' port='-1' autoport='yes'/> <video> <model type='cirrus' vram='9216' heads='1'/> </video> ... </devices>
8. Arrancar la VM y conectarse a VNC con “virt-manager”:
sudo virsh start test_2
9. (VM arrancada con live CD) Con parted eliminar las particiones 2 y 5 y recrearlas. Recomiendo ejecutarlo asi:
parted -a optimal /dev/vda
Cambiamos a sectores como unidad:
u s
Eliminamos particiones:
rm 5 rm 2
Creo la primera, extendida:
mkpart extended 501760 10483711 mkpart logical 503808 10483711
En la segunda he dejado 2048 sectores, que a 512 bytes cada uno hacen 1 MB, que parece ser que es buena practica, ya que de otra forma parted se queja de que las particiones no estan alineadas.
Le quito el flag lba a la particion extendida:
toggle 2 lba
Salgo:
quit
10. (VM arrancada con live CD) Copiar con dd de la particion destino a la origan, una vez recreada:
time dd if=/dev/vdb5 of=/dev/vda5 bs=512
Creo que el proceso de nuevo tiene una velocidad entorno a los 60 MB/s
11. (VM arrancada con live CD) Apagar
sudo shutdon -h now
12. Deshacer los cambios sobre la VM hechos en el paso 7. Si se quiere encerrarlo entre comentarios <!– –> por si hay que repetir algun paso
13. Arrancar la VM
14. Si todo funciona correctamente, borrar el LV de backup creado en el paso 2:
sudo lvremove /dev/vg/lv_test_2_clone
http://blog.gadi.cc/better-lvm-for-kvm/
http://vitobotta.com/kvm-virtual-machines-lvm/#sthash.DSURrZdj.dpbs
Asumo que el PV y el VG ya existen. Vamos a crear un LV por cada VM. Seguimos pues los siguientes pasos:
1. Crear el LV con la extension deseada:
sudo lvcreate vg --name lv_machine_1 --size=8G
NOTA: NO tenemos que formatear el LV, de eso se encarga el guest
2. Ya podemos usar la ruta (Path) al LV como almacenamiento. Ejemplo de clonar una VM:
sudo virt-clone --connect=qemu:///system -o original.example.com -n machine-1.example.com -f /dev/vg/lv_machine_1
1. Apagar la VM
2. Instalar paquete:
sudo aptitude install kpartx
3. Listar todos los LVs del host:
sudo lvdisplay | grep Path
En este caso nos interesa este:
/dev/vg/lv_test_2
4. (Host) Crear el mapeo de dispositivos desde la tabla de particiones:
sudo kpartx -av /dev/mapper/vg-lv_test_2
Salida:
add map vg-lv_test_2p1 (253:9): 0 497664 linear /dev/mapper/vg-lv_test_2 2048 add map vg-lv_test_2p2 (253:11): 0 2 linear /dev/mapper/vg-lv_test_2 501758 add map vg-lv_test_2p5 : 0 9981952 linear /dev/mapper/vg-lv_test_2 501760
5. Listar nuevos LVs y VG:
sudo lvscan
Aparecen estos dos nuevos:
inactive '/dev/template-1/root' [4.51 GiB] inherit inactive '/dev/template-1/swap_1' [252.00 MiB] inherit
Aparece tambien un nuevo VG, al que pertenecen esos dos nuevos LVs:
sudo vgscan
Reading all physical volumes. This may take a while... Found volume group "template-1" using metadata type lvm2
6. Activar el nuevo VG, para que los LVs se puedan montar:
sudo vgchange -ay template-1
Salida:
2 logical volume(s) in volume group "template-1" now active
Comprobar que ahora los LVs estan activos:
sudo lvscan
Aparecen estos dos nuevos:
ACTIVE '/dev/template-1/root' [4.51 GiB] inherit ACTIVE '/dev/template-1/swap_1' [252.00 MiB] inherit
7. Usar los LVs. Por ejemplo lo monto:
touch /tmp/root sudo mount /dev/template-1/root /tmp/root
8. Deshacer los cambios:
8.1. Desmontar:
sudo umount /tmp/root
8.2. Deshabilitar el VG:
sudo vgchange -an template-1
Salida:
0 logical volume(s) in volume group "template-1" now active
8.3. Eliminar el mapeo de dispositivos desde la tabla de particiones:
sudo kpartx -rv /dev/mapper/vg-lv_test_2
Salida:
del devmap : vg-lv_test_2p5 del devmap : vg-lv_test_2p2 del devmap : vg-lv_test_2p1
En este ejemplo le vamos a asignar un LV a una VM.
1. Crear un .xml con la definicion, no importa la ruta:
vim ~/vm_1.xml
<pool type="fs"> <name>template_1</name> <source> <device path="/dev/vg/vm_1"/> </source> <target> <path>/var/lib/libvirt/images/template_1</path> </target> </pool>
2. Crear el directorio “target”
sudo mkdir /var/lib/libvirt/images/template_1
3. Definir el pool storage:
sudo virsh pool-define ~/vm_1.xml
4. Marcarlo para que se inicie al arrancar la maquina:
sudo virsh pool-autostart vm_1
5. Arrancar el pool. Esta accion monta “source” en “target”. Si “target” no existe devuelve un error:
sudo virsh pool-start vm_1
6. Comprobar:
cat /etc/mtab | grep vm_1 /dev/mapper/vg-vm_1 /var/lib/libvirt/images/vm_1 ext4 rw,relatime,data=ordered 0 0
1. Paramos la VM:
sudo shutdown www-1.dev.local.example.com
2. Exportamos el disco de formato 'raw' a 'qcow2':
sudo qemu-img convert -p -O qcow2 /var/lib/libvirt/images/www-1.dev.local.example.com.raw /var/lib/libvirt/images/www-1.dev.local.example.com.qcow2
Se ha creado el nuevo archivo.
3. Editamos la VM:
sudo virsh edit www-1.dev.local.example.com
Y editamos los parametros 'type' y 'source file':
<disk type='file' device='disk'> <driver name='qemu' type='qcow2' cache='none'/> <source file='/var/lib/libvirt/images/www-1.dev.local.example.com.qcow2'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </disk>
Grabamos y salimos
4. Arrancamos la VM:
sudo virsh start www-1.dev.local.example.com
Si arranca correctamente nos cepillamos el disco en formato “raw” que ya no usaremos:
sudo rm -fr www-1.dev.local.example.com.raw
http://serverfault.com/questions/457250/kvm-and-libvirt-how-do-i-hotplug-a-new-virtio-disk
First of all, you should avoid using virsh attach-disk with its limited amount of options. Instead, I suggest to specify the exact disk format you prefer in a separate, temporary XML file, like this:
<disk type='file' device='disk'> <driver name='qemu' type='qcow2' cache='writeback'/> <source file='/home/gert/kvm/testdomain-vdb.img'/> <target dev='vdb' bus='virtio'/> </disk>
Before adding it, make sure the hotplug kernel modules are loaded in the guest:
modprobe acpiphp modprobe pci_hotplug
Some distributions, including recent CentOS/RHEL/Fedora have this built-in in the kernel. In this case, check for CONFIG_HOTPLUG_PCI_ACPI. If it's y, then you're all set.
Finally, add it to the running VM using
virsh # attach-device [domain] /path/to/disk.xml
(optionally, add the –persistent option to let Libvirt update the domain XML definition 'persistent'.)
In the guest, the kernel should now be triggered, as can be checked with dmesg:
[ 321.946440] virtio-pci 0000:00:06.0: using default PCI settings [...] [ 321.952782] vdb: vdb1 vdb2
This also works perfectly using the GUI-enabled virt-manager application.
See also:
http://www.linux-kvm.org/page/Hotadd_pci_devices http://serverfault.com/questions/453456/adding-virtio-block-devices-at-runtime-in-libvirt-kvm
http://redes-privadas-virtuales.blogspot.com.es/2011/03/taking-snapshots-on-kvm-with-libvirt.html
http://www.thegoldfish.org/2011/09/reverting-to-a-previous-snapshot-using-linux-lvm/
Caracteristicas/limitaciones:
Consideraciones y estrategia propuesta:
1. Se puede ejecutar con la VM corriendo. Desde el host ejecutar:
sudo lvcreate -s /dev/vg/lv_vm_1 -L 1G -n lv_vm_1_snapshot_1
1. Crear un nuevo LV para el backup. Tiene que tener el mismo tamanyo que el del LV del cual se tomo el snapshot:
sudo lvcreate vg --name lv_vm_1_snapshot_1_backup --size=8G
2. Copiar con dd el snapshot al backup. Ajustar el block size (bs):
time sudo dd if=/dev/vg/lv_vm_1_snapshot_1 of=/dev/vg/lv_vm_1_snapshot_1_backup bs=512
Velocidad: 50.9 MB/s
3. Eliminar el snapshot:
sudo lvremove /dev/vg/lv_vm_1_snapshot_1
1. Parar la VM
2. Copiar con dd desde el backup al LV original. Ajustar el block size (bs):
time sudo dd if=/dev/vg/lv_vm_1_snapshot_1_backup of=/dev/vg/lv_vm_1 bs=512
Velocidad: 53.8 MB/s
3. Encender la VM
1. Conectarse al hipervisor. Yo por simplicidad lo hago a traves de SSH, pero a lo mejor es posible conectarse desde el cliente con un virsh -c URL
ssh usuario@hipervisor
2. Crear un archivo .xml con informacion sobre el snapshot:
sudo vim /var/lib/libvirt/qemu/snapshot/test2_snapshot_01.xml
Con el siguiente contenido:
<domainsnapshot> <name>test2_snapshot_01_160520121140</name> <description>Fresh install of Debian Squeeze 64 bits</description> </domainsnapshot>
Grabar y salir
3. IMPORTANTE: solo el formato qcow2 soporta snapshots. Vamos a comprobar que formato tiene el disco duro de la VM, que en este ejemplo se llama “test2”
sudo virsh edit test2
De la informacion que muestra nos fijamos en el disco:
... <disk type='file' device='disk'> <driver name='qemu' type='raw'/> <source file='/var/lib/libvirt/images/test2.img'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </disk> ...
Si intentamos tomar el snapshot veremos que NO lo soporta (:q! para salir de la ventana de edicion):
sudo virsh snapshot-create test2 /var/lib/libvirt/qemu/snapshot/test2_snapshot_01.xml error: Requested operation is not valid: Disk '/var/lib/libvirt/images/test2.img' does not support snapshotting
Por lo que volvemos a editar:
sudo virsh edit test2
Y dejamos la seccion de disco tal que asi (solo cambiar qcow2):
... <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/test2.qcow2'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </disk> ...
Grabar y salir
Domain test2 XML configuration edited.
TODO: quiza hay un comando para cambiar el formato del disco
4. Convertir el disco de formato raw a qcow2. La VM debe estar apagada
sudo qemu-img convert -f raw -O qcow2 -o preallocation=metadata /var/lib/libvirt/images/test2.img /var/lib/libvirt/images/test2.qcow2 sudo chown libvirt-qemu:kvm /var/lib/libvirt/images/test2.qcow2
5. Volver a tomar el snapshot:
sudo virsh snapshot-create test2 /var/lib/libvirt/qemu/snapshot/test2_snapshot_01.xml Domain snapshot test2_snapshot_01_160520121140 created from '/var/lib/libvirt/qemu/snapshot/test2_snapshot_01.xml'
Para verlo:
sudo virsh snapshot-list test2 Name Creation Time State ------------------------------------------------------------ test2_snapshot_01_160520121140 2012-05-16 12:46:48 +0200 shutoff
RENDIMIENTO si tomamos el snapshot de una VM corriendo (2GB de disco duro) me tomo 03'14“
6. Arrancar la VM y verificar que funciona correctamente
sudo virsh start test2 Domain test2 started
7. Si ha arrancado correctamente, eliminar el viejo disco:
sudo rm -fr /var/lib/libvirt/images/test2.img
#!/usr/bin/python import sys, commands, time, os, datetime # Variables path_snapshots = '/var/lib/libvirt/qemu/snapshot/' header = ['Id', 'Name', 'State'] snapshot_template = """\ <domainsnapshot> <name>NAME</name> <description>DESCRIPTION</description> </domainsnapshot> """ # Code if not os.geteuid() == 0: print "You aren't root. Goodbye." sys.exit() output = commands.getoutput('virsh list --all') print output list_vm = [line for line in output.split('\n') if '---' not in line and not all(e in line for e in header)] row_number_list_vm = int(raw_input('Select which VM to take snapshot.\nUse line number (1 for " %s" etc...): '\ %(list_vm[0]))) line = list_vm[row_number_list_vm-1] print 'You selected "%s"' %(line) description = raw_input('Please type a description for this snapshot: ') aux = line.split(' ')[0].split(' ') vm_name = aux[len(aux)-1] snapshot_name = vm_name + '_' + str(time.time()).split('.')[0] snapshot_xml_path = path_snapshots + snapshot_name + '.xml' snapshot_xml = snapshot_template.replace('NAME',snapshot_name).replace('DESCRIPTION',description) file = open(snapshot_xml_path, 'w+') file.write(snapshot_xml) file.close() print "WARNING, the process takes a while. For a running machine with 2 GB disk can take 3 minutes" print datetime.datetime.today() output = commands.getstatusoutput('virsh snapshot-create %s %s' %(vm_name,snapshot_xml_path)) if output[0] != 0: print 'Error %s' %(str(output)) print datetime.datetime.today()
1. Conectarse al hipervisor. Yo por simplicidad lo hago a traves de SSH, pero a lo mejor es posible conectarse desde el cliente con un virsh -c URL
ssh usuario@hipervisor
2. Listar las snapshots que tenemos (nuestra VM se llama 'test2'):
sudo virsh snapshot-list test2 Name Creation Time State ------------------------------------------------------------ test2_snapshot_01_160520121140 2012-05-16 12:46:48 +0200 shutoff test2_snapshot_02 2012-05-16 12:58:29 +0200 running test2_snapshot_03 2012-05-16 13:03:33 +0200 running
3. Restaurar por ejemplo segunda (test2_snapshot_02):
sudo virsh snapshot-revert test2 test2_snapshot_02
Tarda un par de segundos
Los snapshots soportan como parametros –children, pero si no se le ha pasado en el momento de tomarlo, son considerados totalmente independientes, es decir, se pueden borar 1 a 1:
sudo virsh snapshot-delete test2 test2_snapshot_02 Domain snapshot test2_snapshot_02 deleted
1. Conectar al hipervisor
ssh USUARIO@HIPERVISOR
2. Pausar la VM a clonar. Durante este tiempo consume recursos pero NO es accesible
sudo virsh suspend template Domain template suspended
3. Clonar la VM:
sudo virt-clone --connect=qemu:///system -o template -n template_clone -f /var/lib/libvirt/images/template_clone.qcow2 Asignando 'template_clone.qcow2' | 2.0 GB 00:02 Clon 'template_clone' creado correctamente.
NOTA: para mayor rendimiento el almacenamiento tiene que ser un LV de LVM previamente creado y NO montado:
sudo virt-clone --connect=qemu:///system -o template -n template_clone -f /dev/lvm_vg/lvm_lv_template_clone
4. Reanudar la VM:
sudo virsh resume template Domain template resumed
Tabla resumen de tiempos
CPU host | Memoria host | Discos host | Formato origen | Formato destino | MB/s |
---|---|---|---|---|---|
2xIntel(R) Core(TM)2 Duo E6750 2.66GHz | 8GB DDR2 800MHz | RAID 1 2xST1000DM003-1CH162 | qcow2 file | qcow2 LV | 105.03 |
El proceso comprende dos pasos: exportar la configuracion del guest y copiar el disco o discos.
El primero es comun para cualquier tipo de disco, y se hace asi:
virsh dumpxml foo > /tmp/foo.xml
El segundo depende del tipo de almacenamiento que se haya escogido.
Copiar el disco o discos. En mi caso lo he hecho con un disco .qcow2, pero hay que documentar como exportar VMs con discos en volumenes LVM
scp /path/disco_1.qcow2 /destino/disco_1.qcow2
time sudo dd if=/dev/vg/lv_test_3 bs=512 | gzip -9 > /srv/no_data/test_3_backup
o
time sudo qemu-img convert -c /dev/vg/lv_test_3 -O qcow2 test.img -p
o
time sudo qemu-img convert /dev/vg/lv_test_3 test_3.img -p
o
time sudo qemu-img convert /dev/vg/lv_test_3 /dev/vg/lv_test_3_clone -p
Metdo | Almacenamiento origen | Formato origen | Almacenamiento destino | Formato destino | AlMB/s |
---|---|---|---|---|---|
dd | ? | ? | ? | ? | 20.2 MB/s |
qemu-img (cambio formato) | ? | ? | ? | ? | 40.3 MB/s |
qemu-img (mantengo formato) | ? | ? | ? | ? | 124.12 MB/s |
qemu-img (mantengo formato, destino LV) | ? | ? | ? | ? | 91.02 MB/s |
qemu-img | LV | raw | LV | raw | 54.61 MB/s |
dd bs=4096 | LV | raw | LV | raw | 57.1 MB/s |
1. Copiar el .xml donde se define la VM y que previamente hemos exportado a una ruta accesible por livbirt-bin:
sudo cp /tmp/vm-1.example.com.xml /etc/libvirt/qemu
2. Editar el archivo para verificar que los siguientes elementos existen o son soportados. en el nuevo hipervisor al que se quiere importar:
<cpu mode='custom' match='exact'> <model fallback='allow'>core2duo</model> <vendor>Intel</vendor> <feature policy='require' name='pbe'/> <feature policy='require' name='tm2'/> <feature policy='require' name='est'/> <feature policy='require' name='smx'/> <feature policy='require' name='ss'/> <feature policy='require' name='dtes64'/> <feature policy='require' name='ht'/> <feature policy='require' name='ds'/> <feature policy='require' name='lahf_lm'/> <feature policy='require' name='tm'/> <feature policy='require' name='cx16'/> <feature policy='require' name='vmx'/> <feature policy='require' name='ds_cpl'/> <feature policy='require' name='pdcm'/> <feature policy='require' name='xtpr'/> <feature policy='require' name='acpi'/> </cpu>
<disk type='file' device='disk'> <driver name='qemu' type='raw' cache='none'/> <source file='/var/lib/libvirt/images/vm-1.example.com.qcow2'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </disk>
<interface type='network'> <mac address='52:54:00:bb:9f:e9'/> <source network='default'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface>
3. Mover/montar el disco a la ruta/punto de montaje especificado por el archivo .xml
4. Definir la VM:
sudo virsh define /etc/libvirt/qemu/vm-1.example.com.xml
5. Si todo ha ido bien ya podemos arrancar la maquina:
sudo virsh start vm-1.example.com
1. Arrancar la red 'default':
sudo virsh net-start default
Salida:
Network default started
2. Restaurar/importar una VM a partir de un archivo:
sudo virt-install --name dns-1.dev.jj.com --ram 512 --disk /var/lib/libvirt/images/dns-1.dev.jj.com.qcow2 --import
Configuraciones de red
Probar con el procedimiento documentado en:
http://libvirt.org/sources/virshcmdref/html/sect-net-start.html
1. Crear directorio:
sudo mkdir /var/lib/libvirt/network
2. Crear archivo de configuracion:
sudo vim /var/lib/libvirt/network/default.xml
Con el siguiente contenido:
<network> <name>default</name> <uuid>066c4de2-ec3f-aebe-742e-dfa7f4de3f28</uuid> <forward mode='nat'/> <bridge name='virbr0' stp='on' delay='0' /> <ip address='10.0.0.1' netmask='255.255.255.0'> </ip> </network>
3. Intentar editar el archivo:
sudo virsh net-create /var/lib/libvirt/network/default.xml
Si da un error, intentar arrancar la red:
sudo virsh net-autostart default
4. Ajustar IP y nombre del bridge de la maquina KVM en las reglas de cortafuegos
1. Editar la red, en este caso “default”:
sudo virsh net-edit default
2. Realizar los cambios y guardarlos
3. AVISO en este punto se pierde conectividad. Reiniciar la red:
sudo virsh net-destroy default; sudo virsh net-start default
Ejemplo de archivo de configuracion de VM:
<domain type='kvm'> <name>template-1.dev.jj.com</name> <uuid>f75dcbdc-8fc9-b50c-6612-c34dfebea16f</uuid> <memory unit='KiB'>1048576</memory> <currentMemory unit='KiB'>524288</currentMemory> <vcpu placement='static'>2</vcpu> <os> <type arch='x86_64' machine='pc-1.1'>hvm</type> <boot dev='hd'/> </os> <features> <acpi/> <apic/> <pae/> </features> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> <emulator>/usr/bin/kvm</emulator> <disk type='file' device='disk'> <driver name='qemu' type='qcow2' cache='none'/> <source file='/var/lib/libvirt/images/template-1.dev.jj.com.qcow2'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </disk> <controller type='usb' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> </controller> <interface type='network'> <mac address='52:54:00:c0:c6:24'/> <source network='default'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface> <serial type='pty'> <target port='0'/> </serial> <console type='pty'> <target type='serial' port='0'/> </console> <memballoon model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </memballoon> </devices> </domain>
http://wiki.qemu.org/Documentation/9psetup
http://libvirt.org/formatdomain.html#elementsFilesystems
http://sourceforge.net/p/v9fs/mailman/v9fs-users/?viewmonth=201310
http://troglobit.com/blog/2013/07/05/file-system-pass-through-in-kvm-slash-qemu-slash-libvirt/
https://www.kernel.org/doc/ols/2010/ols2010-pages-109-120.pdf
NO hace falta cargar los modulos en el host. En los guests ya se cargan por defecto, por tanto no hay que hacer nada a nivel de modolos del kernel.
1. (Hipervisor) Editar la vm en cuestion, mejor si esta apagada:
sudo virsh edit vm_1
Y anyadirle el siguiente bloque, dentro de la seccion <devices>:
... <devices> ... <filesystem type='mount' accessmode='mapped'> <source dir='/srv/data'/> <target dir='tag_srv_data'/> </filesystem> ... </devices> ...
NOTA: tras grabar KVM le anyadira la siguiente linea:
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
2. (Hipervisor) Arrancar la VM:
sudo virsh start vm_1
3. (VM) Montar manualmente la particion:
sudo mkdir /mnt/kvm_9p sudo mount -t 9p -o trans=virtio tag_srv_data /mnt/kvm_9p -oversion=9p2000.L
Con fstab:
/mnt/kvm_9p /mnt/kvm_9p 9p trans=virtio,version=9p2000.L,rw,users,auto 0 0
4. Pruebas:
4.1. Lectura:
sudo ls -la /mnt/kvm_9p
Si hay algun error, consultar los logs del hipervisor y ver si es apparmor el que se queja:
Apr 18 14:03:10 kvm-1 kernel: [446419.384647] type=1400 audit(1366286590.878:72): apparmor="DENIED" operation="open" parent=1 profile="libvirt-c9fcbe04-e995-48eb-0bae-6a00427cb0cf" name="/tmp/test/" pid=6786 comm="pool" requested_mask="r" denied_mask="r" fsuid=106 ouid=0
Si es asi hay que mirar apparmor (TODO)
4.2. Escritura:
touch /mnt/kvm_9p/file
Si obtenemos un error de permiso:
4.2.1. (Hipervisor) Ver con que usuario correo el proceso “qemu-system-x86_64”:
ps aux | grep qemu-system-x86_64
En mi caso:
libvirt+
TODO: ver por que no aparece el nombre completo, que es 'libvirt-qemu'
4.2.2. (Hipervisor) Ajustar los permisos:
sudo chown libvirt-qemu:libvirt-qemu /srv/data
TODO
El proceso es identico a virtfs_9p_mapped con la excepcion que se usa “passthrough” en lugar de “mapped” en el paso 1.
Ademas no se podra escribir (si leer) a no ser que el proceso “qemu-system-x86_64” se ejecute como root.
TODO
https://www.berrange.com/posts/2010/02/15/guest-cpu-model-configuration-in-libvirt-with-qemukvm/
Primero algunos conceptos:
En este ejemplo vamos a ver el antes y el despues en las capacidades CPU de una VM antes y despues de exponerle las capacidades de la CPU del host en el que esta.
1. (Host) Vemos capacidades de la CPU a nivel de sistema operativo:
cat /proc/cpuinfo | grep flags | uniq
O para importar en una tabla:
cat /proc/cpuinfo | grep flags | uniq | cut -d ":" -f2 | sed 's/\ /\n/g' | sort
2. (Host) Repetimos el mismo procedimiento en una VM. Iniciamos sesion en la VM y lanzamos el mismo comando:
cat /proc/cpuinfo | grep flags | uniq
Pongo juntos en una misma tabla los resultados:
Capacidades CPU host | Capacidades CPU guest (antes) | Capacidades CPU guest (despues) |
---|---|---|
acpi | ||
aperfmperf | ||
apic | apic | |
arat | ||
arch_perfmon | ||
bts | ||
clflush | clflush | |
cmov | cmov | |
constant_tsc | ||
cx16 | cx16 | |
cx8 | cx8 | |
de | de | |
ds_cpl | ||
dtes64 | ||
dtherm | ||
dts | ||
epb | ||
ept | ||
est | ||
flexpriority | ||
fpu | fpu | |
fxsr | fxsr | |
ht | hypervisor | |
lahf_lm | lahf_lm | |
lm | lm | |
mca | mca | |
mce | mce | |
mmx | mmx | |
monitor | ||
msr | msr | |
mtrr | mtrr | |
nonstop_tsc | ||
nopl | nopl | |
nx | nx | |
pae | pae | |
pat | ||
pbe | ||
pcid | ||
pclmulqdq | ||
pdcm | ||
pebs | ||
pge | pge | |
pln | ||
pni | pni | |
popcnt | popcnt | |
pse | pse | |
pse36 | pse36 | |
pts | ||
rdtscp | ||
rep_good | rep_good | |
sep | sep | |
ss | ||
sse | sse | |
sse2 | sse2 | |
sse4_1 | ||
sse4_2 | ||
ssse3 | ||
syscall | syscall | |
tm | ||
tm2 | ||
tpr_shadow | ||
tsc | tsc | |
tsc_deadline_timer | ||
vme | ||
vmx | vmx | |
vnmi | ||
vpid | ||
xsave | ||
xsaveopt | ||
xtopology | ||
xtpr |
3. (Host) vemos las capacidades que libvirt nos dice que tiene el host:
sudo virsh capabilities | more
Nos quedamos con el siguiente bloque:
<cpu> <arch>x86_64</arch> <model>Nehalem</model> <vendor>Intel</vendor> <topology sockets='1' cores='2' threads='1'/> <feature name='rdtscp'/> <feature name='osxsave'/> <feature name='xsave'/> <feature name='tsc-deadline'/> <feature name='pdcm'/> <feature name='xtpr'/> <feature name='tm2'/> <feature name='est'/> <feature name='vmx'/> <feature name='ds_cpl'/> <feature name='monitor'/> <feature name='dtes64'/> <feature name='pclmuldq'/> <feature name='pbe'/> <feature name='tm'/> <feature name='ht'/> <feature name='ss'/> <feature name='acpi'/> <feature name='ds'/> <feature name='vme'/> </cpu>
4. (Host) vemos las capacidades que libvirt nos dice que tiene la VM:
sudo virsh dumpxml vm-1.example.com | more
Nos quedamos con el siguiente bloque:
... <vcpu placement='static'>2</vcpu> ...
Como puede observarse no tienen acceso a ninguna de las capacidades de la CPU del host donde corre.
5. Expongo las capacidades de la CPU del host a la VM:
5.1. Apago la VM a nivel de sistema operativo:
ssh vm-1.example.com sudo shutdown -h now
5.2. Edito la VM:
sudo virsh edit vm-1.example.com
En el editor busco el bloque del paso 4:
<vcpu placement='static'>2</vcpu>
Y lo sustituyo por el siguiente bloque, adaptacion del bloque del paso 3:
<cpu mode='custom' match='exact'> <model fallback='allow'>Nehalem</model> <vendor>Intel</vendor> <feature policy='require' name='rdtscp'/> <feature policy='require' name='osxsave'/> <feature policy='require' name='xsave'/> <feature policy='require' name='tsc-deadline'/> <feature policy='require' name='pdcm'/> <feature policy='require' name='xtpr'/> <feature policy='require' name='tm2'/> <feature policy='require' name='est'/> <feature policy='require' name='vmx'/> <feature policy='require' name='ds_cpl'/> <feature policy='require' name='monitor'/> <feature policy='require' name='dtes64'/> <feature policy='require' name='pclmuldq'/> <feature policy='require' name='pbe'/> <feature policy='require' name='tm'/> <feature policy='require' name='ht'/> <feature policy='require' name='ss'/> <feature policy='require' name='acpi'/> <feature policy='require' name='ds'/> <feature policy='require' name='vme'/> </cpu>
Grabo y salgo.
5.3. Compruebo que los cambios se han grabado repitiendo el paso 4.
5.4. Arranco la VM:
sudo virsh start vm-1.example.com
5.5. Repito el paso 2. La salida ahora es diferente. Resumen:
Capacidades CPU host | Capacidades CPU guest (antes) | Capacidades CPU guest (despues) |
---|
| acpi | | |
aperfmperf | ||
apic | apic | apic |
arat | ||
arch_perfmon | ||
bts | ||
clflush | clflush | clflush |
cmov | cmov | cmov |
constant_tsc | ||
cx16 | cx16 | cx16 |
cx8 | cx8 | cx8 |
de | de | de |
ds_cpl | ||
dtes64 | ||
dtherm | ||
dts | ||
epb | ||
ept | ||
est | ||
flexpriority | ||
fpu | fpu | fpu |
fxsr | fxsr | fxsr |
ht | hypervisor | hypervisor |
lahf_lm | lahf_lm | lahf_lm |
lm | lm | lm |
mca | mca | mca |
mce | mce | mce |
mmx | mmx | mmx |
monitor | ||
msr | msr | msr |
mtrr | mtrr | mtrr |
nonstop_tsc | ||
nopl | nopl | nopl |
nx | nx | nx |
pae | pae | pae |
pat | ||
pbe | ||
pcid | ||
pclmulqdq | pclmulqdq | |
pdcm | ||
pebs | ||
pge | pge | pge |
pln | ||
pni | pni | pni |
popcnt | popcnt | popcnt |
pse | pse | pse |
pse36 | pse36 | pse36 |
pts | ||
rdtscp | rdtscp | |
rep_good | rep_good | rep_good |
sep | sep | sep |
ss | ss | |
sse | sse | sse |
sse2 | sse2 | sse2 |
sse4_1 | sse4_1 | |
sse4_2 | sse4_2 | |
ssse3 | ssse3 | |
syscall | syscall | syscall |
tm | ||
tm2 | ||
tpr_shadow | ||
tsc | tsc | tsc |
tsc_deadline_timer | tsc_deadline_timer | |
up | ||
vme | vme | |
vmx | vmx | vmx |
vnmi | ||
vpid | ||
xsave | ||
xsaveopt | ||
xtopology | ||
xtpr |
Conclusiones:
Siempre es bueno ir VM a VM parando servicios de forma controlada, como por ejemplo mysql, pero si tenemos prisa:
1. Parar todas las VMs:
sudo service libvirt-guests stop
Por pantalla va indicando el progreso. Para comprobar siempre haremos un:
sudo virsh list --all
2. Arrancar todas las VMs que esten definidas como autostart:
sudo service libvirt-bin restart
TODO quiza habria que mover esta seccion a un articulo propio
http://libvirt.org/aclpolkit.html
https://wiki.archlinux.org/index.php/libvirt#Using_Python
Ejemplo sencillo de uso sin contrasenya si se dan las siguientes condiciones:
virsh -c qemu:///system list
La url sirve para la API tambien
[('__class__', <class 'libvirt.virConnect'>) ('__del__', <bound method virConnect.__del__ of <libvirt.virConnect object at 0x7f653a08df10>>) ('__delattr__', <method-wrapper '__delattr__' of virConnect object at 0x7f653a08df10>) ('__dict__', {'_o': <capsule object "virConnectPtr" at 0x7f6538716c00>}) ('__doc__', None) ('__format__', <built-in method __format__ of virConnect object at 0x7f653a08df10>) ('__getattribute__', <method-wrapper '__getattribute__' of virConnect object at 0x7f653a08df10>) ('__hash__', <method-wrapper '__hash__' of virConnect object at 0x7f653a08df10>) ('__init__', <bound method virConnect.__init__ of <libvirt.virConnect object at 0x7f653a08df10>>) ('__module__', 'libvirt') ('__new__', <built-in method __new__ of type object at 0x8fbce0>) ('__reduce__', <built-in method __reduce__ of virConnect object at 0x7f653a08df10>) ('__reduce_ex__', <built-in method __reduce_ex__ of virConnect object at 0x7f653a08df10>) ('__repr__', <method-wrapper '__repr__' of virConnect object at 0x7f653a08df10>) ('__setattr__', <method-wrapper '__setattr__' of virConnect object at 0x7f653a08df10>) ('__sizeof__', <built-in method __sizeof__ of virConnect object at 0x7f653a08df10>) ('__str__', <method-wrapper '__str__' of virConnect object at 0x7f653a08df10>) ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x29d7020>) ('__weakref__', None) ('_dispatchCloseCallback', <bound method virConnect._dispatchCloseCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventBalloonChangeCallback', <bound method virConnect._dispatchDomainEventBalloonChangeCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventBlockPullCallback', <bound method virConnect._dispatchDomainEventBlockPullCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventCallbacks', <bound method virConnect._dispatchDomainEventCallbacks of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventDeviceRemovedCallback', <bound method virConnect._dispatchDomainEventDeviceRemovedCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventDiskChangeCallback', <bound method virConnect._dispatchDomainEventDiskChangeCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventGenericCallback', <bound method virConnect._dispatchDomainEventGenericCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventGraphicsCallback', <bound method virConnect._dispatchDomainEventGraphicsCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventIOErrorCallback', <bound method virConnect._dispatchDomainEventIOErrorCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventIOErrorReasonCallback', <bound method virConnect._dispatchDomainEventIOErrorReasonCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventLifecycleCallback', <bound method virConnect._dispatchDomainEventLifecycleCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventPMSuspendCallback', <bound method virConnect._dispatchDomainEventPMSuspendCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventPMSuspendDiskCallback', <bound method virConnect._dispatchDomainEventPMSuspendDiskCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventPMWakeupCallback', <bound method virConnect._dispatchDomainEventPMWakeupCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventRTCChangeCallback', <bound method virConnect._dispatchDomainEventRTCChangeCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventTrayChangeCallback', <bound method virConnect._dispatchDomainEventTrayChangeCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_dispatchDomainEventWatchdogCallback', <bound method virConnect._dispatchDomainEventWatchdogCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('_o', <capsule object "virConnectPtr" at 0x7f6538716c00>) ('baselineCPU', <bound method virConnect.baselineCPU of <libvirt.virConnect object at 0x7f653a08df10>>) ('changeBegin', <bound method virConnect.changeBegin of <libvirt.virConnect object at 0x7f653a08df10>>) ('changeCommit', <bound method virConnect.changeCommit of <libvirt.virConnect object at 0x7f653a08df10>>) ('changeRollback', <bound method virConnect.changeRollback of <libvirt.virConnect object at 0x7f653a08df10>>) ('close', <bound method virConnect.close of <libvirt.virConnect object at 0x7f653a08df10>>) ('compareCPU', <bound method virConnect.compareCPU of <libvirt.virConnect object at 0x7f653a08df10>>) ('createLinux', <bound method virConnect.createLinux of <libvirt.virConnect object at 0x7f653a08df10>>) ('createXML', <bound method virConnect.createXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('createXMLWithFiles', <bound method virConnect.createXMLWithFiles of <libvirt.virConnect object at 0x7f653a08df10>>) ('defineXML', <bound method virConnect.defineXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('domainEventDeregister', <bound method virConnect.domainEventDeregister of <libvirt.virConnect object at 0x7f653a08df10>>) ('domainEventDeregisterAny', <bound method virConnect.domainEventDeregisterAny of <libvirt.virConnect object at 0x7f653a08df10>>) ('domainEventRegister', <bound method virConnect.domainEventRegister of <libvirt.virConnect object at 0x7f653a08df10>>) ('domainEventRegisterAny', <bound method virConnect.domainEventRegisterAny of <libvirt.virConnect object at 0x7f653a08df10>>) ('domainXMLFromNative', <bound method virConnect.domainXMLFromNative of <libvirt.virConnect object at 0x7f653a08df10>>) ('domainXMLToNative', <bound method virConnect.domainXMLToNative of <libvirt.virConnect object at 0x7f653a08df10>>) ('findStoragePoolSources', <bound method virConnect.findStoragePoolSources of <libvirt.virConnect object at 0x7f653a08df10>>) ('getCPUMap', <bound method virConnect.getCPUMap of <libvirt.virConnect object at 0x7f653a08df10>>) ('getCPUModelNames', <bound method virConnect.getCPUModelNames of <libvirt.virConnect object at 0x7f653a08df10>>) ('getCPUStats', <bound method virConnect.getCPUStats of <libvirt.virConnect object at 0x7f653a08df10>>) ('getCapabilities', <bound method virConnect.getCapabilities of <libvirt.virConnect object at 0x7f653a08df10>>) ('getCellsFreeMemory', <bound method virConnect.getCellsFreeMemory of <libvirt.virConnect object at 0x7f653a08df10>>) ('getFreeMemory', <bound method virConnect.getFreeMemory of <libvirt.virConnect object at 0x7f653a08df10>>) ('getHostname', <bound method virConnect.getHostname of <libvirt.virConnect object at 0x7f653a08df10>>) ('getInfo', <bound method virConnect.getInfo of <libvirt.virConnect object at 0x7f653a08df10>>) ('getLibVersion', <bound method virConnect.getLibVersion of <libvirt.virConnect object at 0x7f653a08df10>>) ('getMaxVcpus', <bound method virConnect.getMaxVcpus of <libvirt.virConnect object at 0x7f653a08df10>>) ('getMemoryParameters', <bound method virConnect.getMemoryParameters of <libvirt.virConnect object at 0x7f653a08df10>>) ('getMemoryStats', <bound method virConnect.getMemoryStats of <libvirt.virConnect object at 0x7f653a08df10>>) ('getSecurityModel', <bound method virConnect.getSecurityModel of <libvirt.virConnect object at 0x7f653a08df10>>) ('getSysinfo', <bound method virConnect.getSysinfo of <libvirt.virConnect object at 0x7f653a08df10>>) ('getType', <bound method virConnect.getType of <libvirt.virConnect object at 0x7f653a08df10>>) ('getURI', <bound method virConnect.getURI of <libvirt.virConnect object at 0x7f653a08df10>>) ('getVersion', <bound method virConnect.getVersion of <libvirt.virConnect object at 0x7f653a08df10>>) ('interfaceDefineXML', <bound method virConnect.interfaceDefineXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('interfaceLookupByMACString', <bound method virConnect.interfaceLookupByMACString of <libvirt.virConnect object at 0x7f653a08df10>>) ('interfaceLookupByName', <bound method virConnect.interfaceLookupByName of <libvirt.virConnect object at 0x7f653a08df10>>) ('isAlive', <bound method virConnect.isAlive of <libvirt.virConnect object at 0x7f653a08df10>>) ('isEncrypted', <bound method virConnect.isEncrypted of <libvirt.virConnect object at 0x7f653a08df10>>) ('isSecure', <bound method virConnect.isSecure of <libvirt.virConnect object at 0x7f653a08df10>>) ('listAllDevices', <bound method virConnect.listAllDevices of <libvirt.virConnect object at 0x7f653a08df10>>) ('listAllDomains', <bound method virConnect.listAllDomains of <libvirt.virConnect object at 0x7f653a08df10>>) ('listAllInterfaces', <bound method virConnect.listAllInterfaces of <libvirt.virConnect object at 0x7f653a08df10>>) ('listAllNWFilters', <bound method virConnect.listAllNWFilters of <libvirt.virConnect object at 0x7f653a08df10>>) ('listAllNetworks', <bound method virConnect.listAllNetworks of <libvirt.virConnect object at 0x7f653a08df10>>) ('listAllSecrets', <bound method virConnect.listAllSecrets of <libvirt.virConnect object at 0x7f653a08df10>>) ('listAllStoragePools', <bound method virConnect.listAllStoragePools of <libvirt.virConnect object at 0x7f653a08df10>>) ('listDefinedDomains', <bound method virConnect.listDefinedDomains of <libvirt.virConnect object at 0x7f653a08df10>>) ('listDefinedInterfaces', <bound method virConnect.listDefinedInterfaces of <libvirt.virConnect object at 0x7f653a08df10>>) ('listDefinedNetworks', <bound method virConnect.listDefinedNetworks of <libvirt.virConnect object at 0x7f653a08df10>>) ('listDefinedStoragePools', <bound method virConnect.listDefinedStoragePools of <libvirt.virConnect object at 0x7f653a08df10>>) ('listDevices', <bound method virConnect.listDevices of <libvirt.virConnect object at 0x7f653a08df10>>) ('listDomainsID', <bound method virConnect.listDomainsID of <libvirt.virConnect object at 0x7f653a08df10>>) ('listInterfaces', <bound method virConnect.listInterfaces of <libvirt.virConnect object at 0x7f653a08df10>>) ('listNWFilters', <bound method virConnect.listNWFilters of <libvirt.virConnect object at 0x7f653a08df10>>) ('listNetworks', <bound method virConnect.listNetworks of <libvirt.virConnect object at 0x7f653a08df10>>) ('listSecrets', <bound method virConnect.listSecrets of <libvirt.virConnect object at 0x7f653a08df10>>) ('listStoragePools', <bound method virConnect.listStoragePools of <libvirt.virConnect object at 0x7f653a08df10>>) ('lookupByID', <bound method virConnect.lookupByID of <libvirt.virConnect object at 0x7f653a08df10>>) ('lookupByName', <bound method virConnect.lookupByName of <libvirt.virConnect object at 0x7f653a08df10>>) ('lookupByUUID', <bound method virConnect.lookupByUUID of <libvirt.virConnect object at 0x7f653a08df10>>) ('lookupByUUIDString', <bound method virConnect.lookupByUUIDString of <libvirt.virConnect object at 0x7f653a08df10>>) ('networkCreateXML', <bound method virConnect.networkCreateXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('networkDefineXML', <bound method virConnect.networkDefineXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('networkLookupByName', <bound method virConnect.networkLookupByName of <libvirt.virConnect object at 0x7f653a08df10>>) ('networkLookupByUUID', <bound method virConnect.networkLookupByUUID of <libvirt.virConnect object at 0x7f653a08df10>>) ('networkLookupByUUIDString', <bound method virConnect.networkLookupByUUIDString of <libvirt.virConnect object at 0x7f653a08df10>>) ('newStream', <bound method virConnect.newStream of <libvirt.virConnect object at 0x7f653a08df10>>) ('nodeDeviceCreateXML', <bound method virConnect.nodeDeviceCreateXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('nodeDeviceLookupByName', <bound method virConnect.nodeDeviceLookupByName of <libvirt.virConnect object at 0x7f653a08df10>>) ('nodeDeviceLookupSCSIHostByWWN', <bound method virConnect.nodeDeviceLookupSCSIHostByWWN of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfDefinedDomains', <bound method virConnect.numOfDefinedDomains of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfDefinedInterfaces', <bound method virConnect.numOfDefinedInterfaces of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfDefinedNetworks', <bound method virConnect.numOfDefinedNetworks of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfDefinedStoragePools', <bound method virConnect.numOfDefinedStoragePools of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfDevices', <bound method virConnect.numOfDevices of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfDomains', <bound method virConnect.numOfDomains of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfInterfaces', <bound method virConnect.numOfInterfaces of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfNWFilters', <bound method virConnect.numOfNWFilters of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfNetworks', <bound method virConnect.numOfNetworks of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfSecrets', <bound method virConnect.numOfSecrets of <libvirt.virConnect object at 0x7f653a08df10>>) ('numOfStoragePools', <bound method virConnect.numOfStoragePools of <libvirt.virConnect object at 0x7f653a08df10>>) ('nwfilterDefineXML', <bound method virConnect.nwfilterDefineXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('nwfilterLookupByName', <bound method virConnect.nwfilterLookupByName of <libvirt.virConnect object at 0x7f653a08df10>>) ('nwfilterLookupByUUID', <bound method virConnect.nwfilterLookupByUUID of <libvirt.virConnect object at 0x7f653a08df10>>) ('nwfilterLookupByUUIDString', <bound method virConnect.nwfilterLookupByUUIDString of <libvirt.virConnect object at 0x7f653a08df10>>) ('registerCloseCallback', <bound method virConnect.registerCloseCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('restore', <bound method virConnect.restore of <libvirt.virConnect object at 0x7f653a08df10>>) ('restoreFlags', <bound method virConnect.restoreFlags of <libvirt.virConnect object at 0x7f653a08df10>>) ('saveImageDefineXML', <bound method virConnect.saveImageDefineXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('saveImageGetXMLDesc', <bound method virConnect.saveImageGetXMLDesc of <libvirt.virConnect object at 0x7f653a08df10>>) ('secretDefineXML', <bound method virConnect.secretDefineXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('secretLookupByUUID', <bound method virConnect.secretLookupByUUID of <libvirt.virConnect object at 0x7f653a08df10>>) ('secretLookupByUUIDString', <bound method virConnect.secretLookupByUUIDString of <libvirt.virConnect object at 0x7f653a08df10>>) ('secretLookupByUsage', <bound method virConnect.secretLookupByUsage of <libvirt.virConnect object at 0x7f653a08df10>>) ('setKeepAlive', <bound method virConnect.setKeepAlive of <libvirt.virConnect object at 0x7f653a08df10>>) ('setMemoryParameters', <bound method virConnect.setMemoryParameters of <libvirt.virConnect object at 0x7f653a08df10>>) ('storagePoolCreateXML', <bound method virConnect.storagePoolCreateXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('storagePoolDefineXML', <bound method virConnect.storagePoolDefineXML of <libvirt.virConnect object at 0x7f653a08df10>>) ('storagePoolLookupByName', <bound method virConnect.storagePoolLookupByName of <libvirt.virConnect object at 0x7f653a08df10>>) ('storagePoolLookupByUUID', <bound method virConnect.storagePoolLookupByUUID of <libvirt.virConnect object at 0x7f653a08df10>>) ('storagePoolLookupByUUIDString', <bound method virConnect.storagePoolLookupByUUIDString of <libvirt.virConnect object at 0x7f653a08df10>>) ('storageVolLookupByKey', <bound method virConnect.storageVolLookupByKey of <libvirt.virConnect object at 0x7f653a08df10>>) ('storageVolLookupByPath', <bound method virConnect.storageVolLookupByPath of <libvirt.virConnect object at 0x7f653a08df10>>) ('suspendForDuration', <bound method virConnect.suspendForDuration of <libvirt.virConnect object at 0x7f653a08df10>>) ('unregisterCloseCallback', <bound method virConnect.unregisterCloseCallback of <libvirt.virConnect object at 0x7f653a08df10>>) ('virConnGetLastError', <bound method virConnect.virConnGetLastError of <libvirt.virConnect object at 0x7f653a08df10>>) ('virConnResetLastError', <bound method virConnect.virConnResetLastError of <libvirt.virConnect object at 0x7f653a08df10>>)]
[('ID', <bound method virDomain.ID of <libvirt.virDomain object at 0x7f39740e6750>>) ('OSType', <bound method virDomain.OSType of <libvirt.virDomain object at 0x7f39740e6750>>) ('UUID', <bound method virDomain.UUID of <libvirt.virDomain object at 0x7f39740e6750>>) ('UUIDString', <bound method virDomain.UUIDString of <libvirt.virDomain object at 0x7f39740e6750>>) ('XMLDesc', <bound method virDomain.XMLDesc of <libvirt.virDomain object at 0x7f39740e6750>>) ('__class__', <class 'libvirt.virDomain'>) ('__del__', <bound method virDomain.__del__ of <libvirt.virDomain object at 0x7f39740e6750>>) ('__delattr__', <method-wrapper '__delattr__' of virDomain object at 0x7f39740e6750>) ('__dict__', {'_conn': <libvirt.virConnect object at 0x7f3975a5ff50>, '_o': <capsule object "virDomainPtr" at 0x7f39740e7c90>}) ('__doc__', None) ('__format__', <built-in method __format__ of virDomain object at 0x7f39740e6750>) ('__getattribute__', <method-wrapper '__getattribute__' of virDomain object at 0x7f39740e6750>) ('__hash__', <method-wrapper '__hash__' of virDomain object at 0x7f39740e6750>) ('__init__', <bound method virDomain.__init__ of <libvirt.virDomain object at 0x7f39740e6750>>) ('__module__', 'libvirt') ('__new__', <built-in method __new__ of type object at 0x8fbce0>) ('__reduce__', <built-in method __reduce__ of virDomain object at 0x7f39740e6750>) ('__reduce_ex__', <built-in method __reduce_ex__ of virDomain object at 0x7f39740e6750>) ('__repr__', <method-wrapper '__repr__' of virDomain object at 0x7f39740e6750>) ('__setattr__', <method-wrapper '__setattr__' of virDomain object at 0x7f39740e6750>) ('__sizeof__', <built-in method __sizeof__ of virDomain object at 0x7f39740e6750>) ('__str__', <method-wrapper '__str__' of virDomain object at 0x7f39740e6750>) ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x1d606f0>) ('__weakref__', None) ('_conn', <libvirt.virConnect object at 0x7f3975a5ff50>) ('_o', <capsule object "virDomainPtr" at 0x7f39740e7c90>) ('abortJob', <bound method virDomain.abortJob of <libvirt.virDomain object at 0x7f39740e6750>>) ('attachDevice', <bound method virDomain.attachDevice of <libvirt.virDomain object at 0x7f39740e6750>>) ('attachDeviceFlags', <bound method virDomain.attachDeviceFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('autostart', <bound method virDomain.autostart of <libvirt.virDomain object at 0x7f39740e6750>>) ('blkioParameters', <bound method virDomain.blkioParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockCommit', <bound method virDomain.blockCommit of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockInfo', <bound method virDomain.blockInfo of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockIoTune', <bound method virDomain.blockIoTune of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockJobAbort', <bound method virDomain.blockJobAbort of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockJobInfo', <bound method virDomain.blockJobInfo of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockJobSetSpeed', <bound method virDomain.blockJobSetSpeed of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockPeek', <bound method virDomain.blockPeek of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockPull', <bound method virDomain.blockPull of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockRebase', <bound method virDomain.blockRebase of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockResize', <bound method virDomain.blockResize of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockStats', <bound method virDomain.blockStats of <libvirt.virDomain object at 0x7f39740e6750>>) ('blockStatsFlags', <bound method virDomain.blockStatsFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('connect', <bound method virDomain.connect of <libvirt.virDomain object at 0x7f39740e6750>>) ('controlInfo', <bound method virDomain.controlInfo of <libvirt.virDomain object at 0x7f39740e6750>>) ('coreDump', <bound method virDomain.coreDump of <libvirt.virDomain object at 0x7f39740e6750>>) ('create', <bound method virDomain.create of <libvirt.virDomain object at 0x7f39740e6750>>) ('createWithFiles', <bound method virDomain.createWithFiles of <libvirt.virDomain object at 0x7f39740e6750>>) ('createWithFlags', <bound method virDomain.createWithFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('destroy', <bound method virDomain.destroy of <libvirt.virDomain object at 0x7f39740e6750>>) ('destroyFlags', <bound method virDomain.destroyFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('detachDevice', <bound method virDomain.detachDevice of <libvirt.virDomain object at 0x7f39740e6750>>) ('detachDeviceFlags', <bound method virDomain.detachDeviceFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('diskErrors', <bound method virDomain.diskErrors of <libvirt.virDomain object at 0x7f39740e6750>>) ('emulatorPinInfo', <bound method virDomain.emulatorPinInfo of <libvirt.virDomain object at 0x7f39740e6750>>) ('fSTrim', <bound method virDomain.fSTrim of <libvirt.virDomain object at 0x7f39740e6750>>) ('getCPUStats', <bound method virDomain.getCPUStats of <libvirt.virDomain object at 0x7f39740e6750>>) ('hasCurrentSnapshot', <bound method virDomain.hasCurrentSnapshot of <libvirt.virDomain object at 0x7f39740e6750>>) ('hasManagedSaveImage', <bound method virDomain.hasManagedSaveImage of <libvirt.virDomain object at 0x7f39740e6750>>) ('hostname', <bound method virDomain.hostname of <libvirt.virDomain object at 0x7f39740e6750>>) ('info', <bound method virDomain.info of <libvirt.virDomain object at 0x7f39740e6750>>) ('injectNMI', <bound method virDomain.injectNMI of <libvirt.virDomain object at 0x7f39740e6750>>) ('interfaceParameters', <bound method virDomain.interfaceParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('interfaceStats', <bound method virDomain.interfaceStats of <libvirt.virDomain object at 0x7f39740e6750>>) ('isActive', <bound method virDomain.isActive of <libvirt.virDomain object at 0x7f39740e6750>>) ('isPersistent', <bound method virDomain.isPersistent of <libvirt.virDomain object at 0x7f39740e6750>>) ('isUpdated', <bound method virDomain.isUpdated of <libvirt.virDomain object at 0x7f39740e6750>>) ('jobInfo', <bound method virDomain.jobInfo of <libvirt.virDomain object at 0x7f39740e6750>>) ('jobStats', <bound method virDomain.jobStats of <libvirt.virDomain object at 0x7f39740e6750>>) ('listAllSnapshots', <bound method virDomain.listAllSnapshots of <libvirt.virDomain object at 0x7f39740e6750>>) ('managedSave', <bound method virDomain.managedSave of <libvirt.virDomain object at 0x7f39740e6750>>) ('managedSaveRemove', <bound method virDomain.managedSaveRemove of <libvirt.virDomain object at 0x7f39740e6750>>) ('maxMemory', <bound method virDomain.maxMemory of <libvirt.virDomain object at 0x7f39740e6750>>) ('maxVcpus', <bound method virDomain.maxVcpus of <libvirt.virDomain object at 0x7f39740e6750>>) ('memoryParameters', <bound method virDomain.memoryParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('memoryPeek', <bound method virDomain.memoryPeek of <libvirt.virDomain object at 0x7f39740e6750>>) ('memoryStats', <bound method virDomain.memoryStats of <libvirt.virDomain object at 0x7f39740e6750>>) ('metadata', <bound method virDomain.metadata of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrate', <bound method virDomain.migrate of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrate2', <bound method virDomain.migrate2 of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrate3', <bound method virDomain.migrate3 of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrateGetCompressionCache', <bound method virDomain.migrateGetCompressionCache of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrateGetMaxSpeed', <bound method virDomain.migrateGetMaxSpeed of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrateSetCompressionCache', <bound method virDomain.migrateSetCompressionCache of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrateSetMaxDowntime', <bound method virDomain.migrateSetMaxDowntime of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrateSetMaxSpeed', <bound method virDomain.migrateSetMaxSpeed of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrateToURI', <bound method virDomain.migrateToURI of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrateToURI2', <bound method virDomain.migrateToURI2 of <libvirt.virDomain object at 0x7f39740e6750>>) ('migrateToURI3', <bound method virDomain.migrateToURI3 of <libvirt.virDomain object at 0x7f39740e6750>>) ('name', <bound method virDomain.name of <libvirt.virDomain object at 0x7f39740e6750>>) ('numaParameters', <bound method virDomain.numaParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('openChannel', <bound method virDomain.openChannel of <libvirt.virDomain object at 0x7f39740e6750>>) ('openConsole', <bound method virDomain.openConsole of <libvirt.virDomain object at 0x7f39740e6750>>) ('openGraphics', <bound method virDomain.openGraphics of <libvirt.virDomain object at 0x7f39740e6750>>) ('pMSuspendForDuration', <bound method virDomain.pMSuspendForDuration of <libvirt.virDomain object at 0x7f39740e6750>>) ('pMWakeup', <bound method virDomain.pMWakeup of <libvirt.virDomain object at 0x7f39740e6750>>) ('pinEmulator', <bound method virDomain.pinEmulator of <libvirt.virDomain object at 0x7f39740e6750>>) ('pinVcpu', <bound method virDomain.pinVcpu of <libvirt.virDomain object at 0x7f39740e6750>>) ('pinVcpuFlags', <bound method virDomain.pinVcpuFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('reboot', <bound method virDomain.reboot of <libvirt.virDomain object at 0x7f39740e6750>>) ('reset', <bound method virDomain.reset of <libvirt.virDomain object at 0x7f39740e6750>>) ('resume', <bound method virDomain.resume of <libvirt.virDomain object at 0x7f39740e6750>>) ('revertToSnapshot', <bound method virDomain.revertToSnapshot of <libvirt.virDomain object at 0x7f39740e6750>>) ('save', <bound method virDomain.save of <libvirt.virDomain object at 0x7f39740e6750>>) ('saveFlags', <bound method virDomain.saveFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('schedulerParameters', <bound method virDomain.schedulerParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('schedulerParametersFlags', <bound method virDomain.schedulerParametersFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('schedulerType', <bound method virDomain.schedulerType of <libvirt.virDomain object at 0x7f39740e6750>>) ('screenshot', <bound method virDomain.screenshot of <libvirt.virDomain object at 0x7f39740e6750>>) ('securityLabel', <bound method virDomain.securityLabel of <libvirt.virDomain object at 0x7f39740e6750>>) ('securityLabelList', <bound method virDomain.securityLabelList of <libvirt.virDomain object at 0x7f39740e6750>>) ('sendKey', <bound method virDomain.sendKey of <libvirt.virDomain object at 0x7f39740e6750>>) ('sendProcessSignal', <bound method virDomain.sendProcessSignal of <libvirt.virDomain object at 0x7f39740e6750>>) ('setAutostart', <bound method virDomain.setAutostart of <libvirt.virDomain object at 0x7f39740e6750>>) ('setBlkioParameters', <bound method virDomain.setBlkioParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('setBlockIoTune', <bound method virDomain.setBlockIoTune of <libvirt.virDomain object at 0x7f39740e6750>>) ('setInterfaceParameters', <bound method virDomain.setInterfaceParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('setMaxMemory', <bound method virDomain.setMaxMemory of <libvirt.virDomain object at 0x7f39740e6750>>) ('setMemory', <bound method virDomain.setMemory of <libvirt.virDomain object at 0x7f39740e6750>>) ('setMemoryFlags', <bound method virDomain.setMemoryFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('setMemoryParameters', <bound method virDomain.setMemoryParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('setMemoryStatsPeriod', <bound method virDomain.setMemoryStatsPeriod of <libvirt.virDomain object at 0x7f39740e6750>>) ('setMetadata', <bound method virDomain.setMetadata of <libvirt.virDomain object at 0x7f39740e6750>>) ('setNumaParameters', <bound method virDomain.setNumaParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('setSchedulerParameters', <bound method virDomain.setSchedulerParameters of <libvirt.virDomain object at 0x7f39740e6750>>) ('setSchedulerParametersFlags', <bound method virDomain.setSchedulerParametersFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('setVcpus', <bound method virDomain.setVcpus of <libvirt.virDomain object at 0x7f39740e6750>>) ('setVcpusFlags', <bound method virDomain.setVcpusFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('shutdown', <bound method virDomain.shutdown of <libvirt.virDomain object at 0x7f39740e6750>>) ('shutdownFlags', <bound method virDomain.shutdownFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('snapshotCreateXML', <bound method virDomain.snapshotCreateXML of <libvirt.virDomain object at 0x7f39740e6750>>) ('snapshotCurrent', <bound method virDomain.snapshotCurrent of <libvirt.virDomain object at 0x7f39740e6750>>) ('snapshotListNames', <bound method virDomain.snapshotListNames of <libvirt.virDomain object at 0x7f39740e6750>>) ('snapshotLookupByName', <bound method virDomain.snapshotLookupByName of <libvirt.virDomain object at 0x7f39740e6750>>) ('snapshotNum', <bound method virDomain.snapshotNum of <libvirt.virDomain object at 0x7f39740e6750>>) ('state', <bound method virDomain.state of <libvirt.virDomain object at 0x7f39740e6750>>) ('suspend', <bound method virDomain.suspend of <libvirt.virDomain object at 0x7f39740e6750>>) ('undefine', <bound method virDomain.undefine of <libvirt.virDomain object at 0x7f39740e6750>>) ('undefineFlags', <bound method virDomain.undefineFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('updateDeviceFlags', <bound method virDomain.updateDeviceFlags of <libvirt.virDomain object at 0x7f39740e6750>>) ('vcpuPinInfo', <bound method virDomain.vcpuPinInfo of <libvirt.virDomain object at 0x7f39740e6750>>) ('vcpus', <bound method virDomain.vcpus of <libvirt.virDomain object at 0x7f39740e6750>>) ('vcpusFlags', <bound method virDomain.vcpusFlags of <libvirt.virDomain object at 0x7f39740e6750>>)]
conn = libvirt.open("qemu+ssh://localhost/system") domains = conn.listDefinedDomains()
conn = libvirt.open("qemu+ssh://localhost/system") domains = conn.listDomainsID()