Libvirt API轻量级虚拟机调度(C语言)
来源:互联网 发布:舰娘 mac魔改 编辑:程序博客网 时间:2024/06/16 05:02
实验环境:ubuntu14.04 双网卡(eth0、eth1)
用户级别:root
1 设置root用户
sudo passwd root
输入两次相同密码即可
2 更新源
# apt-get update
3 更新系统软件
# apt-get upgrade
4 安装基础工具
# apt-get install vim ssh gcc vnc4server vncviewer -y
修改ssh配置文件
# vim /etc/ssh/sshd_config
5 安装qemu(不必进行源码安装)
# apt-get install qemu
6 安装网桥
# apt-get install bridge-utils
# apt-get install uml-utilities
7 配置虚拟网桥br0
# vim /etc/network/interfaces
重启网络或者重启系统
重启网络:
# /etc/init.d/networking restart
重启之后,检查网络连接
# ifconfig | more
至此,网桥配置成功
8 安装vnc
# apt-get install vnc4server vncviewer -y
启动vnc
# vncserver
需要设置密码
9 源码安装libvirt
将libvirt1.2.0源码导入/目录下(libvirt源码可以到百度下载)
进入libvirt-1.2.0目录,执行下面操作
可能会出现下面的情况,原因缺少相应的依赖包
# apt-get install libyajl-dev
# apt-get install libxml2-dev
# apt-get install libdevmapper-dev
# apt-get install libpciaccess-dev
# apt-get install libnl-dev
编译源码
# make -j 4
编译完之后,开始安装
# make install
查看是否安装成功,即查看libvirtd进程是否启动
# ps -el | grep libvirtd
如果没有反应,说明libvirt服务没有启动,使用命令开启libvirt
# libvirtd -d
有一种可能就是系统第一次在/usr/local下手动编译安装程序,执行ldconfig命令更新动态链接库缓存,然后再开启libvirt服务
# ldconfig
查看版本
10 使用virsh命令创建一台虚拟机
创建镜像文件
# qemu-img create -f qcow2 ubuntu1.img 10G
上传ubuntu镜像
编写qemu驱动的域的配置文件(暂时命名为demo1.xml,位置在/etc/libvirt/qemu)
<domain type='kvm'>
<name>vm1</name> //虚拟机名称
<memory>1048576</memory> //最大内存,单位k
<currentMemory>1048576</currentMemory> //可用内存,单位k
<vcpu>2</vcpu> //虚拟cpu个数
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='cdrom'/> //光盘启动
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/ubuntu1.img'/> //目的镜像路径
<target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/var/lib/libvirt/images/ubuntu-12.04-server-amd64.iso'/> //光盘镜像路径
<target dev='hdb' bus='ide'/>
</disk>
<interface type='bridge'> //虚拟机网络连接方式
<source bridge='br0'/> //当前主机网桥的名称
<mac address="00:16:3e:5d:aa:b1"/> //为虚拟机分配mac地址,务必唯一,否则dhcp获得同样ip,引起冲突
</interface>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen = '0.0.0.0' keymap='en-us'/>//vnc方式登录,端口号自动分配,自动加1,可以通过virsh vncdisplay来查询
</devices>
</domain>
使用virsh命令开始创建虚拟机
查看虚拟机列表
出现这种情况是没有开启libvirtd服务,使用libvirtd -d开启就行
定义虚拟机
上述情况可能是linux内核中没有安装kvm模块
# apt-get install kvm
安装之后,使用virsh命令定义虚拟机
开启虚拟机
查看vnc端口号
使用vnc打开虚拟机
# vncviewer 127.0.0.1:0
按步骤一步步安装即可
关闭虚拟机
使用demo2.xml打开虚拟机
<domain type='kvm'>
<name>vm2</name>
<memory>524288</memory>
<currentMemory>524288</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/> //即harddisk,从磁盘启动
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/ubuntu1.img'/> //目的镜像路径
<target dev='hda' bus='ide'/>
</disk>
<disk type='file' device='cdrom'>
<source file='/var/lib/libvirt/images/ubuntu-12.04-server-amd64.iso'/> //光盘镜像路径
<target dev='hdb' bus='ide'/>
</disk>
<interface type='bridge'>
<source bridge='br0'/>
<mac address="00:16:3e:5d:aa:b1"/>
</interface>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/>
</devices>
</domain>
使用virsh命令打开虚拟机
查看vnc端口号并使用vncviewer打开虚拟机
关闭虚拟机vm2
关闭虚拟机vm2
以上介绍了使用libvirt virsh工具创建管理虚拟机的过程
下面就介绍一下使用libvirt api 接口调用函数来进行虚拟机的创建和管理
(1)使用libvirt库实现虚拟机连接并查看虚拟机基本信息(使用c语言实现此过程)
打开虚拟机vm2
编写代码libvirt-conn.c:
//libvirt-conn.c
#include <stdio.h>
#include <stdlib.h>
#include <libvirt/libvirt.h>
virConnectPtr conn=NULL;
virConnectPtr getConn(){
conn = virConnectOpenReadOnly(NULL);
if(conn == NULL)
{
printf("error,cann`t connect!");
exit(1);
}
return conn;
}
int getInfo(int id)
{
virDomainPtr dom=NULL;
virDomainInfo info;
conn = getConn();
dom = virDomainLookupByID(conn,id);
if(dom == NULL)
{
printf("error,cann`t find domin!");
virConnectClose(conn);
exit(1);
}
if(virDomainGetInfo(dom,&info)<0)
{
printf("error,cann`t get info!");
virDomainFree(dom);
exit(1);
}
printf("the Domain state is: %d\n",info.state);
printf("the Domain allowed max memory is: %ld KB\n",info.maxMem);
printf("the Domain used memory is: %ld KB\n",info.memory);
printf("the Domain vCPU number is: %d\n",info.nrVirtCpu);
if(dom!=NULL)
{
virDomainFree(dom);
}
if(conn!=NULL)
{
virConnectClose(conn);
}
return 0;
}
int main()
{
getInfo(3);
return 0;
}
编译并运行libvirt-conn.c
从上面可以看到正在运行的虚拟机vm2的信息
使用virt-install命令创建一台虚拟机
(1)创建镜像文件
查看镜像文件信息
(2)使用virt-install命令
virt-install \
--name=vm3 \
--ram 1024 \
--vcpus 2 \
--disk path=/home/cc/images/ubuntu2.img,format=qcow2 \
--cdrom=/home/cc/images/ubuntu-12.04-server-amd64.iso \
--graphics vnc,listen=0.0.0.0,port=5910 --noautoconsole \
--os-type=linux \
--os-variant=ubuntutrusty \
--virt-type=kvm \
--hvm \
--accelerate \
--network bridge=br0
完成安装后,系统会自动默认在/etc/libvirt/qemu目录下创建虚拟机配置文件(vm3.xml)
下面来看一下vm3.xml的内容
<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
virsh edit vm3
or other application using the libvirt API.
-->
<domain type='kvm'>
<name>vm3</name>
<uuid>b76e8d37-976d-4235-a1c3-e358130e23dd</uuid>
<memory unit='KiB'>1048576</memory>
<currentMemory unit='KiB'>1048576</currentMemory>
<vcpu placement='static'>2</vcpu>
<os>
<type arch='x86_64' machine='pc-i440fx-trusty'>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-spice</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/cc/images/ubuntu2.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' target='0' unit='0'/>
</disk>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<interface type='bridge'>
<mac address='52:54:00:33:b0:14'/>
<source bridge='br0'/>
<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='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5910' autoport='no' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<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>
可以看到我们之前设置的一些参数和配置文件的一样
然后我们重新开启它
使用vnc打开虚拟机
至此,使用virt-install创建虚拟机的过程完成
下面编写一些c语言程序,来创建、管理虚拟机
(1)开始界面设计代码,主要是显示管理菜单,代码演示如下:
void start()
{
char enter;
system("clear");
printf("\n\n\n\n");
printf(" ******************************************\n");
printf(" * 欢迎来到我的云平台 *\n");
printf(" ******************************************\n");
printf("\n\n\n");
printf(" 是否进入(y/n):");
scanf("%c",&enter);
if(enter == 'y')
{
printf("\n\n 正在进入,请稍等。。。\n");
sleep(2);
menu();
}
else
{
if(enter == 'n')
{
printf("\n\n 正在退出。。。\n");
sleep(1);
exit(0);
}
else
{
printf("\n\n Error!\n");
exit(1);
}
}
}
void menu()
{
int n = 1;
system("clear");
int i;
printf("\n\n\n");
printf(" ***************************************\n");
printf(" * 云平台管理 *\n");
printf(" ***************************************\n");
printf(" * 1.创建虚拟机 *\n");
printf(" * 2.打开虚拟机 *\n");
printf(" * 3.查看虚拟机 *\n");
printf(" * 4.暂停虚拟机 *\n");
printf(" * 5.恢复虚拟机 *\n");
printf(" * 6.关闭虚拟机 *\n");
printf(" * 7.销毁虚拟机 *\n");
printf(" * 8.删除虚拟机 *\n");
printf(" * 9.退出此系统 *\n");
printf(" ***************************************\n");
printf("\n\n 选择操作序号:");
scanf("%d",&i);
switch(i)
{
case 1:
createVMM();
break;
case 2:
startVMM();
break;
case 3:
printVMM();
break;
case 4:
suspendVMM();
break;
case 5:
resumeVMM();
break;
case 6:
shutVMM();
break;
case 7:
destroyVMM();
break;
case 8:
undefineVMM();
case 9:
quitSys();
break;
default:
printf("\n Error!\n");sleep(2);
exit(0);
}
}
(2)创建虚拟机,先创建到虚拟机的连接,然后根据xml虚拟机配置文件创建一台虚拟机,代码演示如下:
char* getXML(char *name)
{
FILE *fp;
fp = fopen(name,"rb");
if(!fp)
{
printf("文件打开失败!");
}
fseek(fp, 0, SEEK_END);
int file_size = ftell(fp);
char *tmp = (char *) malloc(sizeof(char) * file_size);
fseek(fp, 0, SEEK_SET);
fread(tmp, file_size, sizeof(char), fp);
fclose(fp);
return tmp;
}
virConnectPtr getConn()
{
//创建一个连接
conn = virConnectOpen(NULL);
if(conn == NULL)
{
fprintf(stderr, "Failed to open connection to qemu:///system\n");
exit(1);
}
return conn;
}
void createVMM()
{
char ch;
char *name = "/root/vm1.xml"; //XML文件
const char *xmlconfig = (const char*)getXML(name);
const char *domain_name;
system("clear");
conn = getConn(); //本地连接
dom = virDomainDefineXML(conn,xmlconfig); //定义虚拟机
if(!dom)
{
fprintf(stderr, "\n\n Domain definition failed\n");
sleep(1);
menu();
}
if (virDomainCreate(dom) < 0) //创建虚拟机
{
virDomainFree(dom);
fprintf(stderr, "\n\n Cannot boot guest\n");
printf(" 虚拟机已存在!请销毁!");
undefineVMM(); //删除虚拟机
}
domain_name = virDomainGetName(dom); //得到虚拟机名
printf("\n\n 虚拟机创建成功!\n");
fprintf(stderr, " Guest %s has booted\n", domain_name);
virDomainFree(dom); //释放域
virConnectClose(conn); //关闭连接
sleep(3);
menu();
}
(3)关闭虚拟机,使用virDomainLookupByID得到域,virDomainShutdown关闭虚拟机
void shutVMM(){
int id;
system("clear");
printf("\n\n 正在显示当前活动的虚拟机。。。\n");
sleep(2);
activeVMM();
printf("\n\n 请输入要关闭的虚拟机ID(0返回菜单):");
scanf("%d",&id);
printf("\n --------------------------------\n");
if(id == 0)
{
menu();
}
conn = getConn();
dom = virDomainLookupByID(conn,id);
printf("\n 虚拟机关闭中。。。\n");
sleep(2);
if(virDomainShutdown(dom)<0)
{
fprintf(stderr, "\n Cannot shutdown guest");
sleep(1);
virDomainFree(dom);
virConnectClose(conn);
menu();
}
else
{
sleep(4);
printf("\n 关闭成功!\n");
sleep(3);
printVMM();
}
}
(4)打开虚拟机,使用virDomainLookupByName得到域,使用virDomainCreate打开虚拟机,失败返回-1,代码演示如下:
void startVMM()
{
system("clear");
char *name = (char *) malloc(sizeof(char) * 5);
const char *vm_name;
non_actionVMM();
printf("\n 输入要开启虚拟机名:");
scanf("%s",name);
vm_name = (const char*)name;
conn = getConn();
dom = virDomainLookupByName(conn,vm_name);
free(name);
if(!dom)
{
fprintf(stderr, "\n\n Domain definition failed\n");
printf("\n 虚拟机已存在,请删除!\n");sleep(2);
undefineVMM();
}
if(virDomainCreate(dom)<0)
{
printf(" 虚拟机开启失败!\n");
virDomainFree(dom);
virConnectClose(conn);
sleep(2);
menu();
}
printf("\n 虚拟机开启成功!\n");
virDomainFree(dom);
virConnectClose(conn);
sleep(2);
menu();
}
(5)查看虚拟机信息,比如运行状态、虚拟内存、虚拟CPU个数等,代码演示如下:
void non_actionVMM()
{
int i;
int numDomains;
char **inactiveDomains;
conn = getConn();
numDomains = virConnectNumOfDefinedDomains(conn);
inactiveDomains = malloc(sizeof(char *) * numDomains);
numDomains = virConnectListDefinedDomains(conn, inactiveDomains, numDomains);
printf("\n 非活动虚拟机\n");
printf(" -------------------------------\n");
sleep(1);
printf(" Inactive domain names:\n");
printf(" ");
for (i = 0 ; i < numDomains ; i++) {
printf(" %s\t", inactiveDomains[i]);
free(inactiveDomains[i]);
}
printf("\n");
free(inactiveDomains);
virConnectClose(conn);
}
//当前活动的虚拟机
void activeVMM()
{
int i;
int numDomains;
int *activeDomains;
conn = getConn(); //本地连接
numDomains = virConnectNumOfDomains(conn);
activeDomains = malloc(sizeof(int) * numDomains);
numDomains = virConnectListDomains(conn, activeDomains, numDomains);
printf("\n\n 活动虚拟机\n");
printf(" -------------------------------\n");
printf(" Active domain IDs:\n");
sleep(1);
printf(" ");
for (i = 0 ; i < numDomains ; i++)
{
printf("%d\t", activeDomains[i]);
}
printf("\n");
free(activeDomains);
virConnectClose(conn);
}
void infoVMM(int id)
{
virNodeInfo nodeinfo;
virDomainInfo info;
system("clear");
conn = getConn();
dom = virDomainLookupByID(conn,id);
if(dom == NULL)
{
printf("error,cann`t find domin!");
virConnectClose(conn);
exit(1);
}
if(virDomainGetInfo(dom,&info)<0)
{
printf("error,cann`t get info!");
virDomainFree(dom);
exit(1);
}
virNodeGetInfo(conn, &nodeinfo);
printf("\n 虚拟机信息\n");
printf(" -----------------------------------\n");
printf(" 虚拟机运行状态: %d\n",info.state);
printf(" 虚拟机使用内存大小: %ld KB\n",info.memory);
printf(" 虚拟CPU数量: %d\n",info.nrVirtCpu);
fprintf(stdout, " 虚拟化类型: %s\n", virConnectGetType(conn));
fprintf(stdout, " 操作系统型号: %s\n", nodeinfo.model);
fprintf(stdout, " 内存大小: %luKB\n", nodeinfo.memory);
fprintf(stdout, " CPU数量: %u\n", nodeinfo.cpus);
fprintf(stdout, " CPU频率: %uMHZ\n", nodeinfo.mhz);
fprintf(stdout, " 节点数:%u\n", nodeinfo.nodes);
fprintf(stdout, " CPU进程数: %u\n", nodeinfo.sockets);
fprintf(stdout, " 每个进程的CPU核心数: %u\n", nodeinfo.cores);
fprintf(stdout, " 每个内核的CPU线程数: %u\n", nodeinfo.threads);
virDomainFree(dom);
virConnectClose(conn);
sleep(5);
menu();
}
void printVMM()
{
int id;
system("clear");
printf("\n\n 正在显示当前活动的虚拟机。。。\n");
sleep(2);
activeVMM();
non_actionVMM();
printf(" --------------------------------\n");
printf("\n 请输入虚拟机ID号(0返回菜单):");
scanf("%d",&id);
if(id == 0) menu();
else infoVMM(id);
}
(6)暂停虚拟机,使用virDomainSuspend暂停虚拟机,保持暂停状态,代码演示如下:
void suspendVMM(){
int id;
virDomainInfo info;
system("clear");
printf("\n\n 正在显示当前活动的虚拟机。。。\n");
sleep(2);
activeVMM();
printf("\n\n 请输入要暂停的虚拟机ID(0返回菜单):");
scanf("%d",&id);
printf("\n --------------------------------\n");
if(id == 0)
{
menu();
}
else{
conn = getConn();
dom = virDomainLookupByID(conn,id);
printf(" 暂停中。。。\n");
sleep(4);
if(virDomainSuspend(dom)<0)
{
printf(" error,cann`t suspend domain!\n");
}
if(virDomainGetInfo(dom,&info)<0)
{
printf(" error,cann`t get info!\n");
virDomainFree(dom);
exit(1);
}
printf(" (状态:1.running 3.pause 7.suspend)\n");
printf(" ----------------------------\n");
printf(" 虚拟机运行状态: %d\n",info.state);
virDomainFree(dom);
virConnectClose(conn);
sleep(2);
menu();
}
}
(7)恢复虚拟机,从暂停状态恢复,使用virDomainResume来恢复虚拟机
void resumeVMM(){
int id;
virDomainInfo info;
system("clear");
printf("\n\n 正在显示当前活动的虚拟机。。。\n");
sleep(2);
activeVMM();
printf("\n\n 请输入要恢复的虚拟机ID(0返回菜单):");
scanf("%d",&id);
printf("\n --------------------------------\n");
if(id == 0)
{
menu();
}
else{
conn = getConn();
dom = virDomainLookupByID(conn,id);
printf(" 恢复中。。。\n");
sleep(4);
if(virDomainResume(dom)<0)
{
printf(" error,cann`t suspend domain!\n");
}
if(virDomainGetInfo(dom,&info)<0)
{
printf(" error,cann`t get info!\n");
virDomainFree(dom);
exit(1);
}
printf(" (状态:1.running 7.suspend\n");
printf(" ----------------------------\n");
printf(" 虚拟机运行状态: %d\n",info.state);
virDomainFree(dom);
virConnectClose(conn);
sleep(2);
menu();
}
}
(8)关闭虚拟机
void shutVMM(){
int id;
system("clear");
printf("\n\n 正在显示当前活动的虚拟机。。。\n");
sleep(2);
activeVMM();
printf("\n\n 请输入要关闭的虚拟机ID(0返回菜单):");
scanf("%d",&id);
printf("\n --------------------------------\n");
if(id == 0)
{
menu();
}
conn = getConn();
dom = virDomainLookupByID(conn,id);
printf("\n 虚拟机关闭中。。。\n");
sleep(2);
if(virDomainShutdown(dom)<0)
{
fprintf(stderr, "\n Cannot shutdown guest");
sleep(1);
virDomainFree(dom);
virConnectClose(conn);
menu();
}
else
{
sleep(4);
printf("\n 关闭成功!\n");
sleep(3);
printVMM();
}
}
(9)销毁虚拟机
void destroyVMM(){
int id;
system("clear");
printf("\n\n 正在显示当前活动的虚拟机。。。\n");
sleep(2);
activeVMM();
printf("\n\n 请输入要销毁的虚拟机ID(0返回菜单):");
scanf("%d",&id);
printf("\n --------------------------------\n");
if(id == 0)
{
menu();
}
conn = getConn();
dom = virDomainLookupByID(conn,id);
printf("\n 虚拟机销毁中。。。\n");
sleep(2);
if(virDomainDestroy(dom)<0)
{
fprintf(stderr, "\n Cannot Destroy guest");
sleep(2);
virDomainFree(dom);
virConnectClose(conn);
menu();
}
else
{
sleep(4);
printf("\n 销毁成功!\n");
sleep(3);
printVMM();
}
}
(10)删除虚拟机
//删除虚拟机
void undefineVMM()
{
system("clear");
char *name = (char *) malloc(sizeof(char) * 5);
const char *vm_name;
non_actionVMM();
printf("\n 输入要开启虚拟机名:");
scanf("%s",name);
vm_name = (const char*)name;
conn = getConn();
dom = virDomainLookupByName(conn,vm_name);
if(virDomainUndefine(dom)<0){
printf("\n Undefine is error!");
sleep(2);menu();
}
else{
printf("\n 删除成功!\n");
virDomainFree(dom);
virConnectClose(conn);
sleep(2);menu();
}
}
11总结
在环境搭建环节,libvirt源码安装导致的问题,然而遇到这些问题一开始无从下手,然后就去网上搜解决办法,其实最困难的是在代码编写阶段,
libvirt api 接口需要会运用但是网上可以参考的前辈经验也不多,所以就去官方查看了英文原版开发文档,虽然英语不好,但是有谷歌翻译,一点
一点翻译,弄懂api接口怎么运用,
遇到困难,首先不要盲目,应该先自己分析,实在不会,就查资料,相信你最终一定会解决问题
- Libvirt API轻量级虚拟机调度(C语言)
- libvirt 迁移kvm虚拟机 migrate api
- centos下C编程调用libvirt的API访问KVM虚拟机
- libvirt api 虚拟机动态迁移代码示例(非共享存储)
- libvirt Java API用法连载之libvirt C/Java API介绍与jna/libvirt Java SDK引入(三)
- 一个“轻量级” C 语言协程库
- C语言线程调度
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机启动源码实现(1)
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机启动源码实现(2)
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机启动源码实现(3)
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机启动源码实现(4)
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机动态迁移源码分析
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机动态迁移源码分析
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机动态迁移源码分析
- penStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机启动源码实现(1)
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机启动源码实现(2)
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机启动源码实现(3)
- libvirt创建虚拟机
- Map集合的四种遍历方式
- java基础之面向对象(三)
- hadoop 的调优
- Android 键盘小设置
- jQuery轻量级网页编辑器 选中即可编辑
- Libvirt API轻量级虚拟机调度(C语言)
- getViewTreeObserver
- 必须为多态基类声明 virtual 析构函数
- Error:Failed to resolve: com.android.support:appcompat-v7:25.+d
- 原码乘法、补码乘法
- Erlang中的图形化检测工具总结
- [CSAPP] 存储器层次结构(二)
- 打印订单--bcty365
- ST_VTR_SYS_PARAM*类型的实参跟ST_VTR_SYS_PARAM*类型的形参不兼容