Lots of people had various things to say about the first capabilities
patches (see thread starting here:
https://www.redhat.com/archives/libvir-list/2007-March/msg00153.html).
So I thought I'd try to pull together ideas into a single thread, and
post some information about what this is trying to achieve and some
example proposed XML.
Motivation
----------
At the moment there is a considerable amount of conditional code in
libvirt clients. For example the following code from virt-manager
(src/virtManager/create.py):
if self.connection.get_type() == "QEMU": <------- 1
self.window.get_widget("virt-method-pv").set_sensitive(False)
self.window.get_widget("virt-method-fv").set_active(True)
self.window.get_widget("virt-method-fv-unsupported").hide()
self.window.get_widget("virt-method-fv-disabled").hide()
else:
self.window.get_widget("virt-method-pv").set_sensitive(True)
self.window.get_widget("virt-method-pv").set_active(True)
if virtinst.util.is_hvm_capable(): <--------- 2
self.window.get_widget("virt-method-fv").set_sensitive(True)
self.window.get_widget("virt-method-fv-unsupported").hide()
self.window.get_widget("virt-method-fv-disabled").hide()
This hopefully demonstrates two points which I'd like to fix: Firstly
having code which requires knowledge of what a driver is capable of
(line 1 above) is not scalable as we add more and more types of
virtualisation (OpenVZ, VMWare, ...). Secondly the virtinst.util module
does some probing to find out what the local hardware is capable of
(line 2 above), and that won't work over remote connections.
Thirdly, although you can only really connect to one driver at a time
(except in the Xen case, but that's just weird), the <domain>
description required by virDomainCreateLinux is to some extent
driver-specific. So you need additional logic when creating domains,
and for some of those (eg. qemu/kqemu/kvm) it's non-trivial and depends
on information that you "just know" about the driver.
The proposed new API ("virConnectGetCapabilities") would return an XML
description of the capabilities of the driver / hypervisor. In the
remote case, probing would be done on the remote machine. In either
case the idea would be to remove conditional code from virt-manager,
remove local hardware probing from virtinst, and provide some
description of what optional features the <domain> XML supports.
In the next two sections I'll analyse the problem areas in the current
virtinst and virt-manager. You may want to skip the next two sections
and go straight to the example XML.
Analysis of virtinst
--------------------
The main issue is with virtinst/util.py which contains the following
functions which do local probing:
(1) is_pae_capable: host supports PAE? Uses Linux-specific /proc/cpuinfo
(2) is_hvm_capable: host supports HVM & enabled in Xen? Uses
Xen-specific /sys/hypervisor/properties/capabilities
(3) is_kqemu_capable: [Linux] kernel supports kqemu? Uses
Linux-specific /dev/kqemu
(4) is_kvm_capable: [Linux] kernel supports kvm? Uses Linux-specific
/dev/kvm
In virtinst/FullVirtGuest.py:
(5) "emulator" and "loader" must be specified for Xen/QEMU and Xen
guests respectively. They have architecture- and distro-specific paths
which refer to files on the remote machine.
In virtinst/ParaVirtGuest.py:
(6) Uses "xm console" to connect to the console in the Xen case (but
then this sort of paravirtualisation implies Xen).
In virtinst/DistroManager.py:
(7) We download the kernel and boot.iso files, and download and modify
the initrd file. [Comment: I'm not sure that capabilities can solve
this, but it does need to be fixed properly for the remote case to work].
Analysis of virt-manager
------------------------
In src/virtManager/create.py:
(8) Tries to detect if VT-x/AMD-V is present in the hardware but
disabled in the BIOS by doing some Xen-specific heuristics.
(9) Paravirt and fullvirt dialogs are enabled based on the type of the
connection (eg. if self.connection.get_type() == "QEMU" it disables
paravirt).
(10) CPU architecture combo box is enabled only for type == "QEMU".
(11) Similarly, the "accelerate" checkbox is enabled only for type ==
"QEMU". [Comment: Dan tells me that this requirement comes about
because kqemu is sometimes unreliable, so users need a way to disable it].
(12) Local media are required for FV installs. Also we use HAL to
detect media inserted and removed. [Comment: Can be solved separately by
abstracting storage].
In the *.glade files:
(13) The list of CPU architectures for qemu is hard-coded in the
interface description file.
Other areas which are beyond the role of capabilities:
* Remote console
* Serial console
* Saving images
Proposed XML format
-------------------
My thoughts are that capabilities need to return the following
information about the underlying driver/hypervisor:
* Host CPU flags (1,8)
* List of guest architectures supported. For each of these:
- Model of virtualised CPU (10,13)
example: x86_64
- Name of the virtualised machine (if applic.)
example: pc
- Virtualised CPU features: PAE, ...
- Fullvirt flag: can we run an unmodified OS as a guest? (2,9)
or Paravirt: what sort of paravirt API does a guest need
(eg. xen, pvops, VMI, ...)?
- The <domain type='?'> for this guest
example: kqemu
- The <domain><os><type machine='?'> for this guest (if
applic.)
example: pc
- Suggested emulator and loader paths (5)
- Driver-specific flags which libvirt clients would not be
required to understand, but could be used to enhance
libvirt clients.
examples: uses kqemu, uses kvm (3,4,11)
(Notes: (a) I have flattened qemu's nested arch/machine list, because I
there is not a natural hierarchy. (b) The guest architectures list is a
Cartesian product, although at the moment the worst case (qemu) would
only have about 14 entries. An alternate way to do this is discussed at
the end. (c) The host CPU model is already provided by virNodeGetInfo).
Example: Xen
------------
For Xen the primary source for capabilities are the files
/sys/hypervisor/properties/capabilities and /proc/cpuinfo. A Xen driver
might present the following description of its capabilities:
<capabilities>
<host>
<cpu_flags>
<cpu_flag> vmx </cpu_flag>
<cpu_flag> pae </cpu_flag> <!-- etc -->
</cpu_flags>
</host>
<guest_architectures>
<guest_architecture>
<model> x86_64 </model>
<paravirt> xen </paravirt>
<domain_type> xen </domain_type>
<emulator> /usr/lib/xen/bin/qemu-dm </emulator>
</guest_architecture>
<guest_architecture>
<model> i686 </model>
<pae/>
<paravirt> xen </paravirt>
<domain_type> xen </domain_type>
<emulator> /usr/lib/xen/bin/qemu-dm </emulator>
</guest_architecture>
<guest_architecture>
<model> i686 </model>
<fullvirt/>
<domain_type> xen </domain_type>
<loader> /usr/lib/xen/boot/hvmloader </loader>
<emulator> /usr/lib/xen/bin/qemu-dm </emulator>
</guest_architecture>
<guest_architecture>
<model> i686 </model>
<pae/>
<fullvirt/>
<domain_type> xen </domain_type>
<loader> /usr/lib/xen/boot/hvmloader </loader>
<emulator> /usr/lib/xen/bin/qemu-dm </emulator>
</guest_architecture>
<guest_architecture>
<model> x86_64 </model>
<fullvirt/>
<domain_type> xen </domain_type>
<loader> /usr/lib/xen/boot/hvmloader </loader>
<emulator> /usr/lib/xen/bin/qemu-dm </emulator>
</guest_architecture>
</guest_architectures>
</capabilities>
Example: qemu + kqemu + kvm
---------------------------
Qemu has by far the longest list of supported guest architectures. Out
of the box it supports 10 distinct machine types and then you can add 4
extra machine types if the kernel can do kqemu and kvm, making 14 in
all. Below I have abbreviated this list for clarity.
<capabilities>
<host>
<cpu_flags>
<cpu_flag> vmx </cpu_flag>
<cpu_flag> pae </cpu_flag> <!-- etc -->
</cpu_flags>
</host>
<guest_architectures>
<guest_architecture>
<model> sparc </model>
<machine> sun4m </machine>
<fullvirt/>
<domain_type> qemu </domain_type>
<machine_type> sun4m </machine_type>
<emulator> /usr/bin/qemu-system-sparc </emulator>
</guest_architecture>
<guest_architecture>
<model> i686 </model>
<machine> pc </machine>
<fullvirt/>
<domain_type> qemu </domain_type>
<machine_type> pc </machine_type>
<emulator> /usr/bin/qemu </emulator>
</guest_architecture>
<guest_architecture>
<model> x86_64 </model>
<machine> pc </machine>
<fullvirt/>
<domain_type> kqemu </domain_type>
<machine_type> pc </machine_type>
<emulator> /usr/bin/qemu </emulator>
<qemu_uses_kqemu />
</guest_architecture>
<guest_architecture>
<model> x86_64 </model>
<machine> pc </machine>
<fullvirt/>
<domain_type> kvm </domain_type>
<machine_type> pc </machine_type>
<emulator> /usr/bin/qemu-kvm </emulator>
<qemu_uses_kvm />
</guest_architecture>
</guest_architecture>
</capabilities>
Guest architectures: Cartesian product or UI builder?
-----------------------------------------------------
Currently the list of guest architectures is a flat list, worst case 5
entries long for Xen and 14 entries long for qemu. Presenting this in
user interfaces could be challenging.
One suggestion is that the user interface looks like:
[*] Show only fullvirt
[*] Show only PC architectures
[ ] Show 32 bit architectures
[*] Show 64 bit architectures
| Shorter list of architectures which match
| the criteria checked above.
| ...
|
Another is that we change the XML description so that it matches the UI.
For instance:
<guest_architecture>
<models> <model> sparc </model> <model> ppc </model>
...
Or:
<pae> <can_enable/> <can_disable/> </pae>
This is relatively easy to do with qemu, but the format of Xen's
/sys/hypervisor/properties/capabilities makes it quite hard.
i18n
----
Some proposed features may make translation challenging. For example
qemu supports a whole list of machine types ("pc", "sun4m", etc.) and
it
would be nice for libvirt clients to be able to provide some sort of
description for the user. It would not be wise to carry this
description in the XML because it would not be possible to localise it.
To avoid all libvirt clients duplicating and maintaining lists of
machine types and descriptions, it may be worth adding a call to the API
along the lines of:
virConnectGetMachineDescription (const char *machine_name,
const char *lang);
(where lang == NULL would mean to use the current language).
[EOF]
--
Emerging Technologies, Red Hat
http://et.redhat.com/~rjones/
64 Baker Street, London, W1U 7DF Mobile: +44 7866 314 421
"[Negative numbers] darken the very whole doctrines of the equations
and make dark of the things which are in their nature excessively
obvious and simple" (Francis Maseres FRS, mathematician, 1759)