1. 程式人生 > >centos下C程式設計呼叫libvirt的API訪問KVM虛擬機器

centos下C程式設計呼叫libvirt的API訪問KVM虛擬機器

一、簡介

        libvirt是一套免費、開源的支援Linux下主流虛擬化工具的C函式庫,其旨在為包括Xen在內的各種虛擬化工具提供一套方便、可靠的程式設計介面,支援與C,C++,Ruby,Python等多種主流開發語言的繫結。當前主流Linux平臺上預設的虛擬化管理工具virt-manager(圖形化),virt-install(命令列模式)等均基於libvirt開發而成。
       本文基於libvirt,使用它的C函式庫進行虛擬機器的相應操作。

二、詳解

1、建立虛擬機器

(1)C語言程式碼

/*************************************************************************** 
     *  create_kvm.c  
     *  create kvm machine(domain) based on conf.xml 
     *  compile command: 'gcc -g -Wall create_kvm.c -o create -lvirt' 
     *  run shell command:'qemu-img create -f qcow2 newlinux.img 15G'
     *  running command: './create ./create_kvm.xml' 
***************************************************************************/  
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<assert.h>
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>

static int create_kvm();
static int get_status();
static int open_file(char *file_name);

static virConnectPtr conn = NULL;
static virDomainPtr dom = NULL;
char *buff = NULL;

int main(int argc, char *argv[])
{
  if (argc != 2) {
    fprintf(stderr, "parametes are wrong,please checkout!\n");
    return -1;
  }
  if (open_file(argv[1]) != 0) {
    fprintf(stderr, "open_file failed!\n");
    return -1;
  }
  conn = virConnectOpen("qemu:///system");
  if (conn == NULL) {
    fprintf(stderr, "Failed to open connection to qemu:///system\n");
    return -1;
  }
  if (create_kvm() != 0) {
    fprintf(stderr, "create_kvm failed!\n");
    virConnectClose(conn);
    return -1;
  }
  if (get_status() != 0) {
    fprintf(stderr, "create_kvm failed!\n");
    virDomainFree(dom);
    virConnectClose(conn);
    return -1;
  }
  if (dom != NULL)  virDomainFree(dom);
  if (conn != NULL)  virConnectClose(conn);
  return 0;
}
int open_file(char *file_name)
{
   FILE *fp = fopen(file_name, "r+");
   assert(fp);
   int flag = fseek(fp, 0, SEEK_END);
   assert(flag == 0);
   int len = ftell(fp);
   buff = (char *)malloc(sizeof(char) * (len + 1));
   flag = fseek(fp, 0, SEEK_SET);
   assert(flag == 0);
   int num = fread(buff, 1, len + 1, fp);
   assert(num == len);
   return 0;
}
int create_kvm()
{
  dom = virDomainDefineXML(conn, buff);
  if (!dom) {
    virErrorPtr error = virGetLastError();
    fprintf(stderr, "virDomainDefineXML failed:%s!\n", error->message);
    virFreeError(error);
    return -1;
  }
  if (virDomainCreate(dom) < 0) {
    virErrorPtr error = virGetLastError();
    fprintf(stderr, "virDomainCreate failed:%s!\n", error->message);
    virDomainUndefine(dom);
    virFreeError(error);
    //virDomainFree(dom);
    return -1;
  }
  return 0;
}

int get_status()
{
  char *status = NULL;
  virErrorPtr error = NULL;
  int vcpus = 0;
  unsigned long long node_free_memory = 0;
  int id = 0;
  const char *name = NULL;
  virNodeInfo nodeinfo;
  virDomainInfo info; 
  // 獲取虛擬機器狀態
  fprintf(stdout, "****************************************************\n");
  /* get the capabilities of conn*/
  status =  virConnectGetCapabilities(conn);
  if (status == NULL) {
    error = virGetLastError();
    fprintf(stderr, "virConnectGetCapabilities failed: %s\n", error->message);
    virFreeError(error);
    return -1;
  }
  fprintf(stdout, "Capabilities of connection:\t%s\n", status);
  free(status);  status = NULL;

  /* get the hostname reported from conn*/
  status = virConnectGetHostname(conn);
  if (status == NULL) {
    error = virGetLastError();
    fprintf(stderr, "virConnectGetHostname failed: %s\n", error->message);
    virFreeError(error);
    return -1;
  }
  fprintf(stdout, "Connection hostname:\t%s\n", status);
  free(status);  status = NULL;

  /* get the maximum number of vcpus supported by conn3 */
  vcpus = virConnectGetMaxVcpus(conn, NULL);
  if (vcpus < 0) {
    error = virGetLastError();
    fprintf(stderr, "virConnectGetMaxVcpus failed: %s\n", error->message);
    virFreeError(error);
    return -1;
   }
   fprintf(stdout, "Maximum number of cpus supported on connection:\t%d\n", vcpus);

   /* get the amount of free memory available on the node from conn4 */
    node_free_memory = virNodeGetFreeMemory(conn);
    if (node_free_memory == 0) {
      error = virGetLastError();
      fprintf(stderr, "virNodeGetFreeMemory failed: %s\n", error->message);
      virFreeError(error);
      return -1;
   }
   fprintf(stdout, "Node free memory:\t%llu\n", node_free_memory);

   /* get the node information from conn*/
   if (virNodeGetInfo(conn, &nodeinfo) < 0) {
      error = virGetLastError();
      fprintf(stderr, "virNodeGetInfo failed: %s\n", error->message);
      virFreeError(error);
      return -1;
   }
   fprintf(stdout, "Node information from connection\n");
   fprintf(stdout, "Model:\t%s\n", nodeinfo.model);
   fprintf(stdout, "Memory size:\t%lukb\n", nodeinfo.memory);
   fprintf(stdout, "Number of CPUs:\t%u\n", nodeinfo.cpus);
   fprintf(stdout, "MHz of CPUs:\t%u\n", nodeinfo.mhz);
   fprintf(stdout, "Number of NUMA nodes:\t%u\n", nodeinfo.nodes);
   fprintf(stdout, "Number of CPU sockets:\t%u\n", nodeinfo.sockets);
   fprintf(stdout, "Number of CPU cores per socket:\t%u\n", nodeinfo.cores);
   fprintf(stdout, "Number of CPU threads per core:\t%u\n", nodeinfo.threads);
   fprintf(stdout, "****************************************************\n");
   fprintf(stdout, "id\t名稱\t\t狀態\n");
   fprintf(stdout, "------------------------------------------\n");
   id = virDomainGetID(dom);
   name = virDomainGetName(dom);
   if (virDomainGetInfo(dom, &info) < 0) {
     error = virGetLastError();
     fprintf(stderr, "virDomainGetInfo failed: %s\n", error->message);
     virFreeError(error);
     return -1;
   }
   fprintf(stdout, "%d\t%s\t\t%d\n", id, name, info.state);
   fprintf(stdout, "****************************************************\n");
   return 0;
}
(2)建立所需要的啟動配置xml檔案        首先需要準備好centos6.3.iso系統映象檔案,在xml中<source file = '/home/taiyang/centos6.3.iso'/>設定其全路徑。
       然後建立img虛擬機器映象檔案#qemu-img create -f qcow2 newlinux.img 15G,在 <source file = '/var/lib/libvirt/images/newlinux.img'/>設定其路徑。
      最後#vim create_kvm.xml,輸入一下內容:

<domain type = 'kvm'>        //虛擬機器型別,kvm
<name>newlinux</name>        //虛擬機器名稱
<memory>1048576</memory>     //分配記憶體,單位kb
<vcpu>1</vcpu>               //分配vcpu,單位個數
<os>
  <type arch = 'x86_64' machine = 'pc'>hvm</type>
  <boot dev = 'cdrom'/> //cd 啟動
  <boot dev = 'hd'/>    //硬碟啟動
</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/libexec/qemu-kvm</emulator>
    <disk type = 'file' device = 'disk'>  //對應的映象,就是之前使用qemu-img命令新建的img檔案,注意路徑要正確
      <driver name = 'qemu' type = 'qcow2'/>
      <source file = '/var/lib/libvirt/images/newlinux.img'/>
      <target dev = 'hda' bus = 'ide'/>
    </disk>
    <disk type = 'file' device = 'cdrom'> //可選項,iso通常是作業系統的安裝光碟
      <source file = '/home/taiyang/centos6.3.iso'/>
      <target dev = 'hdb' bus = 'ide'/>
    </disk>
    <interface type = 'bridge'>           //libvirt預設虛擬機器的網路配置是NAT模式,就是虛擬機器與宿主機的網路拓撲是NAT形式。實際中,許多開發者更希望使用網橋模式。
      <source bridge = 'virbr0'/>
    </interface>

    <input type ='tablet' bus='usb'/>
    <input type = 'mouse' bus = 'ps2'/>
    <graphics type = 'vnc' port = '-1' listen = '0.0.0.0' keymap = 'en-us'/>  //vnc埠系統自動配置
  </devices>
</domain>
注意:<memory>1048576</memory>單位kb,分配記憶體過大無法啟動;檔案路徑不正確無法啟動。

(3)編譯執行

#gcc -g -Wall create_kvm.c -o create -lvirt

#./create create_kvm.xml

可以通過virsh檢視建立的虛擬機器:


也可以通過virt-manager檢視建立的虛擬機器:

2、操作虛擬機器(開機、關機、查詢狀態)

(1)C語言程式碼

/*   gcc -g -Wall virtctl.c -o virtctl -lvirt      */
/*   virtctl  guest-name  start/shutdown/status    */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>

static int set_start(char *guestname);
static int set_shutdown(char *guestname);
static int get_status(char *guestname);
static virConnectPtr conn = NULL;
static virDomainPtr dom = NULL;

int main(int argc, char *argv[])
{
  if (argc != 3) {
    fprintf(stderr, "Usage:./virtctl guest-name start/shutdown/status\n");
    return -1;
  }
  conn = virConnectOpen("qemu:///system");
  if (conn == NULL) {
    fprintf(stderr, "Failed to open connection to qemu:///system\n");
    return -1;
  }
  dom = virDomainLookupByName(conn, argv[1]);
  if (dom == NULL) {
    fprintf(stderr, "virDomainLookupByName failed!\n");
    virConnectClose(conn);
    return -1;
  }

  if (strcmp(argv[2], "start") == 0 || strcmp(argv[2], "START") == 0) {
    if (set_start(argv[1]) != 0) {
      fprintf(stderr, "start failed!\n");
      virDomainFree(dom);
      //virConnectClose(conn);
      return -1;
    }
  }
  if (strcmp(argv[2], "shutdown") == 0 || strcmp(argv[2], "SHUTDOWN") == 0) {
    if (set_shutdown(argv[1]) != 0) {
      fprintf(stderr, "shutdown failed!\n");
      virConnectClose(conn);
      virDomainFree(dom);
      return -1;
    }
  }
  if (strcmp(argv[2], "status") == 0 || strcmp(argv[2], "STATUS") == 0) {
    if (get_status(argv[1]) != 0) {
      fprintf(stderr, "get status failed!\n");
      virDomainFree(dom);
      virConnectClose(conn);
      return -1;
    }
  }
  if (dom != NULL)  virDomainFree(dom);
  if (conn != NULL)  virConnectClose(conn);
  return 0;
}
int set_start(char *guestname)
{
  int flag = -1;
  // 啟動已定義虛擬機器
  flag = virDomainCreate(dom);
  if (flag != 0) {
    virErrorPtr error = virGetLastError();
    fprintf(stderr, "virDomainCreate failed:%s!\n", error->message);
    virFreeError(error);
    return -1; 
  }
  return 0;
}
int set_shutdown(char *guestname)
{
  int flag = -1;
   // 關閉已定義虛擬機器
  flag = virDomainShutdown(dom);
  if(flag != 0) { 
    virErrorPtr error = virGetLastError();
    fprintf(stderr, "virDomainShutdown failed:%s!\n", error->message);
    virFreeError(error);
    return -1; 
  }
  return 0;
}
int get_status(char *guestname)
{
  char *status = NULL;
  virErrorPtr error = NULL;
  int vcpus = 0;
  unsigned long long node_free_memory = 0;
  int id = 0;
  const char *name = NULL;
  virNodeInfo nodeinfo;
  virDomainInfo info; 
  // 獲取虛擬機器狀態
  fprintf(stdout, "****************************************************\n");
  /* get the capabilities of conn*/
  status =  virConnectGetCapabilities(conn);
  if (status == NULL) {
    error = virGetLastError();
    fprintf(stderr, "virConnectGetCapabilities failed: %s\n", error->message);
    virFreeError(error);
    return -1;
  }
  //fprintf(stdout, "Capabilities of connection:\n%s\n", status);
  free(status);  status = NULL;

  /* get the hostname reported from conn*/
  status = virConnectGetHostname(conn);
  if (status == NULL) {
    error = virGetLastError();
    fprintf(stderr, "virConnectGetHostname failed: %s\n", error->message);
    virFreeError(error);
    return -1;
  }
  //fprintf(stdout, "------------------------------------------\n");
  fprintf(stdout, "Connection hostname:\t%s\n", status);
  free(status);  status = NULL;

  /* get the maximum number of vcpus supported by conn3 */
  vcpus = virConnectGetMaxVcpus(conn, NULL);
  if (vcpus < 0) {
    error = virGetLastError();
    fprintf(stderr, "virConnectGetMaxVcpus failed: %s\n", error->message);
    virFreeError(error);
    return -1;
   }
   fprintf(stdout, "Maximum number of cpus supported on connection:\t%d\n", vcpus);

   /* get the amount of free memory available on the node from conn4 */
    node_free_memory = virNodeGetFreeMemory(conn);
    if (node_free_memory == 0) {
      error = virGetLastError();
      fprintf(stderr, "virNodeGetFreeMemory failed: %s\n", error->message);
      virFreeError(error);
      return -1;
   }
   fprintf(stdout, "Node free memory:\t%llu\n", node_free_memory);

   /* get the node information from conn*/
   if (virNodeGetInfo(conn, &nodeinfo) < 0) {
      error = virGetLastError();
      fprintf(stderr, "virNodeGetInfo failed: %s\n", error->message);
      virFreeError(error);
      return -1;
   }
   fprintf(stdout, "------------------------------------------\n");
   fprintf(stdout, "Node information from connection\n");
   fprintf(stdout, "Model:\t%s\n", nodeinfo.model);
   fprintf(stdout, "Memory size:\t%lukb\n", nodeinfo.memory);
   fprintf(stdout, "Number of CPUs:\t%u\n", nodeinfo.cpus);
   fprintf(stdout, "MHz of CPUs:\t%u\n", nodeinfo.mhz);
   fprintf(stdout, "Number of NUMA nodes:\t%u\n", nodeinfo.nodes);
   fprintf(stdout, "Number of CPU sockets:\t%u\n", nodeinfo.sockets);
   fprintf(stdout, "Number of CPU cores per socket:\t%u\n", nodeinfo.cores);
   fprintf(stdout, "Number of CPU threads per core:\t%u\n", nodeinfo.threads);
   fprintf(stdout, "****************************************************\n");
   fprintf(stdout, "id\t名稱\t\t狀態\n");
   fprintf(stdout, "------------------------------------------\n");
   id = virDomainGetID(dom);
   name = virDomainGetName(dom);
   if (virDomainGetInfo(dom, &info) < 0) {
     error = virGetLastError();
     fprintf(stderr, "virDomainGetInfo failed: %s\n", error->message);
     virFreeError(error);
     return -1;
   }
   fprintf(stdout, "%d\t%s\t\t%d\n", id, name, info.state);
   fprintf(stdout, "****************************************************\n");
   return 0;
}

(2)編譯執行

#gcc -g -Wall virtctl.c -o virtctl -lvirt

#./virtctl newlinux status

****************************************************
Connection hostname:	localhost.localdomain
Maximum number of cpus supported on connection:	16
Node free memory:	1381175296
------------------------------------------
Node information from connection
Model:	x86_64
Memory size:	3823996kb
Number of CPUs:	4
MHz of CPUs:	3200
Number of NUMA nodes:	1
Number of CPU sockets:	1
Number of CPU cores per socket:	2
Number of CPU threads per core:	2
****************************************************
id	名稱		狀態
------------------------------------------
8	newlinux		1
****************************************************

3、virsh命令列管理工具

Libvirt有兩種控制方式,命令列和圖形介面

(1)圖形介面:通過執行名virt-manager,啟動libvirt的圖形介面,在圖形介面下可以一步一步的建立虛擬機器,管理虛擬機器,還可以直接控制虛擬機器的桌面。

(2)virsh所有命令列:

    help            列印幫助
    attach-device   從一個XML檔案附加裝置
    attach-disk     附加磁碟裝置
    attach-interface 獲得網路介面
    autostart       自動開始一個域
    capabilities    效能
    cd              change the current directory
    connect         連線(重新連線)到 hypervisor
    console         連線到客戶會話
    cpu-baseline    compute baseline CPU
    cpu-compare     compare host CPU with a CPU described by an XML file
    create          從一個 XML 檔案建立一個域
    start           開始一個(以前定義的)非活躍的域
    destroy         刪除一個域
    detach-device   從一個 XML 檔案分離裝置
    detach-disk     分離磁碟裝置
    detach-interface 分離網路介面
    define          從一個 XML 檔案定義(但不開始)一個域
    domid           把一個域名或 UUID 轉換為域 id
    domuuid         把一個域名或 id 轉換為域 UUID
    dominfo         域資訊
    domjobinfo      domain job information
    domjobabort     abort active domain job
    domname         將域 id 或 UUID 轉換為域名
    domstate        域狀態
    domblkstat      獲得域裝置塊狀態
    domifstat       獲得域網路介面狀態
    dommemstat      get memory statistics for a domain
    domblkinfo      domain block device size information
    domxml-from-native Convert native config to domain XML
    domxml-to-native Convert domain XML to native config
    dumpxml         XML 中的域資訊
    edit            編輯某個域的 XML 配置
    find-storage-pool-sources 發現潛在儲存池源
    find-storage-pool-sources-as 找到潛在儲存池源
    freecell        NUMA可用記憶體
    hostname        列印管理程式主機名
    list            列出域
    migrate         將域遷移到另一個主機中
    migrate-setmaxdowntime set maximum tolerable downtime
    net-autostart   自動開始網路
    net-create      從一個 XML 檔案建立一個網路
    net-define      從一個 XML 檔案定義(但不開始)一個網路
    net-destroy     刪除一個網路
    net-dumpxml     XML 中的網路資訊
    net-edit        為網路編輯 XML 配置
    net-list        列出網路
    net-name        把一個網路UUID 轉換為網路名
    net-start       開始一個(以前定義的)不活躍的網路
    net-undefine    取消定義一個非活躍的網路
    net-uuid        把一個網路名轉換為網路UUID
    iface-list      list physical host interfaces
    iface-name      convert an interface MAC address to interface name
    iface-mac       convert an interface name to interface MAC address
    iface-dumpxml   interface information in XML
    iface-define    define (but don't start) a physical host interface from an XML file
    iface-undefine  undefine a physical host interface (remove it from configuration)
    iface-edit      edit XML configuration for a physical host interface
    iface-start     start a physical host interface (enable it / "if-up")
    iface-destroy   destroy a physical host interface (disable it / "if-down")
    managedsave     managed save of a domain state
    nodeinfo        節點資訊
    nodedev-list    這臺主機中中的列舉裝置
    nodedev-dumpxml XML 中的節點裝置詳情
    nodedev-dettach dettach node device from its device driver
    nodedev-reattach reattach node device to its device driver
    nodedev-reset   重置節點裝置
    nodedev-create  create a device defined by an XML file on the node
    nodedev-destroy destroy a device on the node
    nwfilter-define define or update a network filter from an XML file
    nwfilter-undefine undefine a network filter
    nwfilter-dumpxml network filter information in XML
    nwfilter-list   list network filters
    nwfilter-edit   edit XML configuration for a network filter
    pool-autostart  自動啟動某個池
    pool-build      建立池
    pool-create     從一個 XML 檔案中建立一個池
    pool-create-as  從一組變數中建立一個池
    pool-define     在一個 XML 檔案中定義(但不啟動)一個池
    pool-define-as  在一組變數中定義池
    pool-destroy    銷燬池
    pool-delete     刪除池
    pool-dumpxml    XML 中的池資訊
    pool-edit       為儲存池編輯 XML 配置
    pool-info       儲存池資訊
    pool-list       列出池
    pool-name       將池 UUID 轉換為池名稱
    pool-refresh    重新整理池
    pool-start      啟動一個(以前定義的)非活躍的池
    pool-undefine   取消定義一個不活躍的池
    pool-uuid       把一個池名稱轉換為池 UUID
    secret-define   define or modify a secret from an XML file
    secret-dumpxml  secret attributes in XML
    secret-set-value set a secret value
    secret-get-value Output a secret value
    secret-undefine undefine a secret
    secret-list     list secrets
    pwd             print the current directory
    quit            退出這個非互動式終端
    exit            退出這個非互動式終端
    reboot          重新啟動一個域
    restore         從一個存在一個檔案中的狀態恢復一個域
    resume          重新恢復一個域
    save            把一個域的狀態儲存到一個檔案
    schedinfo       顯示/設定日程安排變數
    dump            把一個域的核心 dump 到一個檔案中以方便分析
    shutdown        關閉一個域
    setmem          改變記憶體的分配
    setmaxmem       改變最大記憶體限制值
    setvcpus        改變虛擬 CPU 的號
    suspend         掛起一個域
    ttyconsole      tty 控制檯
    undefine        取消定義一個非活躍的域
    update-device   update device from an XML file
    uri             列印管理程式典型的URI
    vol-create      從一個 XML 檔案建立一個卷
    vol-create-from create a vol, using another volume as input
    vol-create-as   從一組變數中建立卷
    vol-clone       clone a volume.
    vol-delete      刪除卷
    vol-wipe        wipe a vol
    vol-dumpxml     XML 中的卷資訊
    vol-info        儲存卷資訊
    vol-list        列出卷
    vol-pool        returns the storage pool for a given volume key or path
    vol-path        returns the volume path for a given volume name or key
    vol-name        returns the volume name for a given volume key or path
    vol-key         returns the volume key for a given volume name or path
    vcpuinfo        域 vcpu 的資訊
    vcpupin         控制域 vcpu affinity
    version         顯示版本
    vncdisplay      vnc 顯示
    snapshot-create Create a snapshot
    snapshot-current Get the current snapshot
    snapshot-delete Delete a domain snapshot
    snapshot-dumpxml Dump XML for a domain snapshot
    snapshot-list   List snapshots for a domain
    snapshot-revert Revert a domain to a snapshot

其中總結常用的命令:

virsh -c qemu:///system                       #連線本機

virsh -c qemu+ssh://[email protected]   #連線遠端libvirt,也可通過connect命令

virsh list                                                 #顯示本地活動虛擬機器

virsh list --all                                         #顯示本地所有的虛擬機器(活動的+不活動的)

virsh define create_kvm.xml              #通過配置檔案定義一個虛擬機器(這個虛擬機器還不是活動的)

virsh start newlinux                             #啟動名字為virtual的非活動虛擬機器

virsh create create_kvm.xml              # 建立虛擬機器(建立後,虛擬機器立即執行,成為活動主機)

virsh suspend newlinux                     # 暫停虛擬機器

virsh resume newlinux                       # 啟動暫停的虛擬機器

virsh shutdown newlinux                   # 正常關閉虛擬機器

virsh destroy newlinux                       # 強制關閉虛擬機器

virsh dominfo newlinux                     #顯示虛擬機器的基本資訊

virsh domname 2                                # 顯示id號為2的虛擬機器名

virsh domid newlinux                        # 顯示虛擬機器id號

virsh domuuid newlinux                   # 顯示虛擬機器的uuid

virsh domstate newlinux                   # 顯示虛擬機器的當前狀態

virsh dumpxml newlinux                   # 顯示虛擬機器的當前配置檔案(可能和定義虛擬機器時的配置不同,因為當虛擬機器啟動時,需要給虛擬機器分配id號、uuid、vnc埠號等等)

virsh setmem newlinux 512000      #給不活動虛擬機器設定記憶體大小

virsh setvcpus newlinux 4                # 給不活動虛擬機器設定cpu個數

virsh edit newlinux                            # 編輯配置檔案(一般是在剛定義完虛擬機器之後)

例1:virsh建立kvm虛擬機器
#qemu-img create -f qcow2 newlinux.qcow2 15G    //製作虛擬機器映象
#vim create_kvm.xml                        //建立配置檔案
#virsh define create_kvm.xml          //建立虛擬機器
#virsh start newlinux                        //啟動虛擬機器
#virsh vncdisplay newlinux            //檢視虛擬機器的vnc埠,然後就可以通過vnc登入 #vncviewer :0來完成虛擬機器的安裝
例2:Add CDROM
#virsh attach-disk guest01 /root/disc1.iso hdc --driver file --type cdrom  --mode readonly 

例3:Change CDROM

#virsh attach-disk guest01 /root/disc2.iso hdc --driver file --type cdrom --mode readonly

例4:Remove CDROM

#virsh attach-disk guest01 " " hdc --driver file --type cdrom --mode readonly

三、參考

四、總結

(1)Libvirt涉及內容眾多,可以先了解qemu-img、virsh、virt-manager、virt-install等工具。

(2)有時間的可以下載開源的Libvirt原始碼分析,這樣對自己的幫助更大。