libvirt原理和API
libvirt架构
架构介绍
- libvirt分为client和deamon两个部分
- libvirt deamon中还包含了rpc,acl,事件机制,线程池等公共组件。基于rpc可以实现libvirt remote client对本地虚拟机的操作。acl实现了访问控制标签。事件机制是libvirt所有动作的基础,所有的请求,消息转发,事件触发都是通过事件机制传递的。
- libvirt deamon中通过事件机制监听某个端口的消息。client发出的请求会通过socket连接发送到libvirt api。
- libvirt deamon在启动时会加载部署的hypervisor驱动,libvirt api接收到的请求会路由到conn对象指定的驱动程序中。
- 驱动程序接收到转发的请求之后会与hypervisor交互实现对虚拟机的具体操作。
- libvirt中目前实现了多种hypervisor的驱动,其中qemu_driver对应kvm,lxc对应容器。
- 对于kvm而言,一个虚拟机对应一个qemu进程。qemu进程通过软件模拟计算机的主板,CPU,南北桥及内存设备。虚拟机操作系统就运行在qemu进程内。
- libvirt独立实现了lxc driver来管理容器。lxc driver启动一个独立的进程并使用这个进程拉起一个init子进程,这个子进程有其独立的namespace并与cgroup结合实现了容器资源的隔离和限制。
接口调用
在libvirt中接口的调用方式分为两种:
远程调用
本地调用
从nova到libvirt openstack是基于Python实现的,而libvirt是基于C实现的。那么C和Python之间是如何转换的呢。下面以启动虚拟机实例来看一下在openstack中如何调用libvirt接口:
- import python-libvirt库
if libvirt is None:
libvirt = __import__('libvirt')
- 通过openAuth获取与libvirtd进程的连接conn
return tpool.proxy_call(
(libvirt.virDomain, libvirt.virConnect),
libvirt.openAuth, uri, auth, flags)
- 调用define接口创建一个虚拟机实例,获取domain对象
domain = self._conn.defineXML(xml)
- 通过domain对象启动虚拟机实例
domain.createWithFlags(launch_flags)
由这个流程我们可以看到,openstack中主要通过python-libvirt库与libvirtd进程交互,完成对虚拟机实例的操作。python-libvirt是由libvirt提供的一个面向python client的连接组件,包含以下内容:
/usr/share/pyshared/libvirt.py #libvirt python接口文件,包含大部分的libvirt接口
/usr/share/pyshared/libvirt_lxc.py #lxc接口文件,因为这部分接口参数不能自动转换,所以通过手动重写完成转换
/usr/share/pyshared/libvirt_qemu.py #与上面的类似,qemu相关的。
/usr/lib/python2.7/dist-packages/libvirtmod_qemu.so
/usr/lib/python2.7/dist-packages/libvirtmod_lxc.so
/usr/lib/python2.7/dist-packages/libvirtmod.so
在libvirt代码中有一个专门的目录用于存放接口python化相关的代码。所有的libvirt接口被分为了两个部分:
- 可以直接自动转换的接口,使用py直接封装python接口
- 无法直接自动转换的接口,通过libvirt-override.c等文件对C接口做一层封装再封装python接口。 libvirt-python工程会将未重写和重写过的接口编译到一个动态库中,并且和生成的py文件一起打包到python-libvirt包中。然后我们就可以通过引入这个python库的方式调用libvirt的C接口了。
Libvirt XML
XML配置
XML地址:https://libvirt.org/formatdomain.html
域、网络、网络过滤、存储、存储加密、能力、域能力、存储池能力、节点设备、秘密、快照、检查点、备份任务的XML模式描述
Libvirt API
Libvirt 概述
https://github.com/libvirt/libvirt
Libvirt提供了一种便携式,长期稳定的C语言API,用于管理许多操作系统提供的虚拟化技术。它包括对QEMU,KVM,XEN,LXC,BHYVE,Virtuozzo,VMware Vcenter和ESX,VMware Desktop,Hyper-V,VirtualBox和Power Hypervisor的支持。
对于其中一些虚拟机管理程序,它提供了一个状态管理守护程序,该守护程序在虚拟化主机上运行,允许非私有的本地用户和远程用户访问API。
分层软件包将libvirt c api的绑定到其他语言中,包括python,perl,php,go,java,ocaml,以及映射到诸如Gobject,CIM和SNMP之类的对象系统中。
API架构介绍
API for Python
地址:https://libvirt.org/python.html
源码:https://github.com/libvirt/libvirt-python
安装:https://pypi.org/project/libvirt-python/#description
部署:pip install libvirt-python
import libvirt
import sys
try:
conn = libvirt.openReadOnly(None)
except libvirt.libvirtError:
print('Failed to open connection to the hypervisor')
sys.exit(1)
try:
dom0 = conn.lookupByName("Domain-0")
except libvirt.libvirtError:
print('Failed to find the main domain')
sys.exit(1)
print("Domain 0: id %d running %s" % (dom0.ID(), dom0.OSType()))
print(dom0.info())
C 和Python对比
支持的API对比
主要功能
全部功能:https://libvirt.org/html/index.html
- libvirt-common: common macros and enums for the libvirt and libvirt-admin library
- libvirt-domain-checkpoint: APIs for management of domain checkpoints
- libvirt-domain-snapshot: APIs for management of domain snapshots
- libvirt-domain: APIs for management of domains
- libvirt-event: APIs for management of events
- libvirt-host: APIs for management of hosts
- libvirt-interface: APIs for management of interfaces
- libvirt-network: APIs for management of networks
- libvirt-nodedev: APIs for management of nodedevs
- libvirt-nwfilter: APIs for management of nwfilters
- libvirt-secret: APIs for management of secrets
- libvirt-storage: APIs for management of storage pools and volumes
- libvirt-stream: APIs for management of streams
- virterror: error handling interfaces for the libvirt library
接口转换关系
https://libvirt.org/python.html
- C语言API里的一些全局函数,对应于Python版本里的特定类的成员函数,比如:int virDomainSetMemory(virDomainPtr domain, unsigned long memory); 这是一个C语言的全局函数,它对应于Python中的类virDomain的成员函数setMemory()
- C语言里面的一些宏,比如 XXX,到了Python中体现为 libvirt.XXX.
- C语言里面一些指向结构体的指针,尤其是该指针被用作函数的入参同时也是出参的时候,到了Python中就体现为该函数的返回值是一个dict. 比如,int virDomainMemoryStats(virDomainPtr dom, virDomainMemoryStatPtr stats, unsigned int nr_stats, unsigned int flags) 这个函数,到了Python中就体现为 virDomain::memoryStats(),该函数没有入参,返回值是一个dict,包含了'actual', 'available'等keys,分别表示实际总内存量、可得内存量等等。
- libvirt 是一个 C 动态库,其 Python API 由 libvirt-python项目下的py 生成。
一部分 Python API 通过 libvirt 的 C API 定义自动生成
$ ls /usr/share/libvirt/api/
libvirt-admin-api.xml libvirt-api.xml libvirt-lxc-api.xml libvirt-qemu-api.xml
一部分 Python API 通过 override API 定义(即对 libvirt C API 有一定的封装)自动生成
$ ls *.xml
libvirt-lxc-override-api.xml libvirt-override-api.xml libvirt-qemu-override-api.xml
一部分 Python API 手工实现
$ ls libvirt-override*.py
libvirt-override.py libvirt-override-virNetwork.py
libvirt-override-virConnect.py libvirt-override-virStoragePool.py
libvirt-override-virDomain.py libvirt-override-virStream.py
libvirt-override-virDomainSnapshot.py
Python API 对应的动态库 wrapper so 一部分由 C API 定义自动生成,一部分由 override API 定义自动生成,其对应的 c 代码实现为
$ ls *-override.c
libvirt-lxc-override.c libvirt-override.c libvirt-qemu-override.c
通过如下命令生成 Python API (build/lib.linux-x86_64-2.7/libvirt.py) 及 wrapper so 动态库 (build/lib.linux-x86_64-2.7/libvirtmod.so):
$ ./setup.py build
$ tree build/
build/
├── lib.linux-x86_64-2.7
│ ├── libvirt_lxc.py
│ ├── libvirtmod_lxc.so
│ ├── libvirtmod_qemu.so
│ ├── libvirtmod.so
│ ├── libvirt.py
│ └── libvirt_qemu.py
├── libvirt.c
├── libvirt-export.c
├── libvirt.h
├── libvirt-lxc.c
├── libvirt-lxc-export.c
├── libvirt-lxc.h
├── libvirt_lxc.py
├── libvirt.py
├── libvirt-qemu.c
├── libvirt-qemu-export.c
├── libvirt-qemu.h
├── libvirt_qemu.py
其中:
- build/lib.linux-x86_64-2.7/libvirt.py 是从 build/libvirt.py 拷贝过去的;
- build/libvirt.py 由 libvirt-override.py 手写部分和
- so由 libvirt-override.c, build/libvirt.c, typewrappers.c, libvirt-utils.c 构建;
- so由 libvirt-qemu-override.c, build/libvirt-qemu.c, typewrappers.c, libvirt-utils.c 构建;
- so由 libvirt-lxc-override.c, build/libvirt-lxc.c, typewrappers.c, libvirt-utils.c 构建;
需要主要的是,Python 绑定中的方法名相比 libvirt C 接口的函数名去掉了前缀,如 libvirt-domain.c/virDomainDefineXML 接口在 Python 绑定中就变成了 virConnect.defineXML。
版本矩阵图
qemu版本和libvirt提供的API接口的版本支持关系
https://libvirt.org/hvsupport.html