目标和术语
目标
提供一个公共且稳定的软件层,足以安全地管理节点(node)(可能是远程节点)上的域(domain)。
术语
- 节点(node):是一台物理机器;
- 虚拟机管理程序(hypervisor):是一个软件层,允许将一个节点虚拟化为多个虚拟机,且虚拟机中的配置可能与所在节点不同;
- 域(domain):是虚拟机管理程序提供的虚拟机上运行的操作系统实例(或容器虚拟化情况下的子系统);
对外暴露的对象
- virConnectPtr:表示与虚拟机管理程序的连接(connection);
- virDomainPtr:表示一个活动的或者已定义的域(已定义的域:表示作为永久配置文件和存储存在,但当前未在该节点上运行);
- virNetworkPtr:表示一个活动的或者已定义的网络;
- virStoragePoolPtr:表示一个存储卷;
- virStorageVolPtr:表示一个存储池,用于分配和存储存储卷的逻辑区域;
libvirt驱动程序
libvirt公共API将其实现委托给各个内部的驱动,当我们使用connection URI
连接到libvirt时,相对应的虚拟化管理程序驱动就会被初始化。比如:我们指定如下的connection URI
,那我们就连接到了一个test
driver中(一个假的虚拟机管理程序驱动)。
virsh -c test:///default
libvirt实现了很多虚拟机管理程序驱动,如:LXC、QEMU/KVM、Xen、VirtualBox、Test等。详情
test
driver
libvirt项目用test
dirvier是用来做UT测试的。测试驱动中的所有状态都保存在内存中,我们可以通过test
driver加载默认配置或者配置文件中定义的虚拟域数据。
一个libvirt项目中使用到的一组test
driver配置文件。
driver加载代码走读
driver代码实现
每个driver都有一个xxx_driver.c文件,对应的就是各个驱动的实现逻辑。比如:test
driver的实现代码在test_driver.c文件中。
而每个驱动源文件都有个注册函数用于把drivers都加载到内存中。还是以test
driver为例,注册函数如下所示:
/**
* testRegister:
*
* Registers the test driver
*/
int
testRegister(void)
{
return virRegisterConnectDriver(&testConnectDriver,
false);
}
在virRegisterConnectDriver()
中有个全局静态变量static virConnectDriver *virConnectDriverTab[MAX_DRIVERS]
,就是管理所有注册的drivers。
URI如何映射到注册driver
- 获取到URL名
当我们输入virsh --connect URI
时,virsh就会获取到URI信息。源码
...
switch (arg) {
/* c表示的是执行virsh命令时带有connect指令 */
case 'c':
VIR_FREE(ctl->connname);
ctl->connname = g_strdup(optarg);
break;
...
- 通过uri获取connection
在virsh的virshConnect()
函数中通过调用virConnectOpenAuth()
函数获取到connection。 源码
do {
...
virErrorPtr err;
if ((c = virConnectOpenAuth(uri, virConnectAuthPtrDefault,
readonly ? VIR_CONNECT_RO : 0)))
break;
if (readonly)
goto cleanup;
...
} while (authfail < 5);
...
cleanup:
virPolkitAgentDestroy(pkagent);
return c;
}
- 加载驱动
因为URI中已经有了各个驱动的前缀schema,所以我们就可以通过这个schema加载相关驱动。比如: 我们要连接到这个URI:test:///default,那这个前缀schema就是test,通过这个前缀我们就能连接到test
driver中。 源码
static virConnectPtr
virConnectOpenInternal(const char *name,
virConnectAuthPtr auth,
unsigned int flags)
{
...
/* 获取到各个驱动的注册函数,比如:test driver那注册函数就是testRegister() */
regMethod = g_strdup_printf("%sRegister", ret->uri->scheme);
/* 通过dlsym()动态加载注册函数 */
if (virDriverLoadModule(ret->uri->scheme, regMethod, false) < 0)
return NULL;
...
}
守护进程和远程访问
libvirt允许我们通过授权及加密的connection来访问运行在远端机器的虚拟机管理程序。