libvirt save接口扩展

背景

想让libvirt在执行save之后,能够处于paused状态,而不是直接关机;对接口进行扩展,增加flags位,实现该功能。

代码实现

需要支持python API调用和virsh 命令执行,改变的文件如下:

 (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   include/libvirt/libvirt-domain.h
	modified:   src/qemu/qemu_driver.c
	modified:   src/qemu/qemu_process.c
	modified:   tools/virsh-domain.c

代码如下:

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 5d3e15766e..bf3a202c60 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1268,6 +1268,7 @@ typedef enum {
     VIR_DOMAIN_SAVE_BYPASS_CACHE = 1 << 0, /* Avoid file system cache pollution */
     VIR_DOMAIN_SAVE_RUNNING      = 1 << 1, /* Favor running over paused */
     VIR_DOMAIN_SAVE_PAUSED       = 1 << 2, /* Favor paused over running */
+    VIR_DOMAIN_PAUSE_AFTER_SAVE  = 1 << 3, /* Favor paused after saved */
 } virDomainSaveRestoreFlags;
 
 int                     virDomainSave           (virDomainPtr domain,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b8537a4260..76b420aaf7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2742,6 +2742,7 @@ qemuDomainSaveInternal(virQEMUDriver *driver,
 {
     g_autofree char *xml = NULL;
     bool was_running = false;
+    bool pause_after_save = false;
     int ret = -1;
     virObjectEvent *event = NULL;
     qemuDomainObjPrivate *priv = vm->privateData;
@@ -2782,6 +2783,12 @@ qemuDomainSaveInternal(virQEMUDriver *driver,
         was_running = true;
     else if (flags & VIR_DOMAIN_SAVE_PAUSED)
         was_running = false;
+    VIR_INFO("jorhson: the flags=0x%x",flags);
+   /*   */
+    if (flags & VIR_DOMAIN_PAUSE_AFTER_SAVE){
+       VIR_INFO("jorhson: To set the flags");
+       pause_after_save = true;
+    }
 
     /* Get XML for the domain.  Restore needs only the inactive xml,
      * including secure.  We should get the same result whether xmlin
@@ -2822,12 +2829,18 @@ qemuDomainSaveInternal(virQEMUDriver *driver,
     if (ret < 0)
         goto endjob;
 
-    /* Shut it down */
-    qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED,
-                    QEMU_ASYNC_JOB_SAVE, 0);
-    virDomainAuditStop(vm, "saved");
-    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
+    if (!pause_after_save){
+       VIR_INFO("jorhson: To stop vm after save");
+       /* Shut it down */
+       qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED,
+       QEMU_ASYNC_JOB_SAVE, 0);
+       virDomainAuditStop(vm, "saved");
+               
+       event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
                                               VIR_DOMAIN_EVENT_STOPPED_SAVED);
+    }else {
+       VIR_INFO("jorhson: To pause vm after save");
+    }
  endjob:
     if (ret < 0) {
         if (was_running && virDomainObjIsActive(vm)) {
@@ -2869,7 +2882,8 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml,
 
     virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
                   VIR_DOMAIN_SAVE_RUNNING |
-                  VIR_DOMAIN_SAVE_PAUSED, -1);
+                  VIR_DOMAIN_SAVE_PAUSED |
+                  VIR_DOMAIN_PAUSE_AFTER_SAVE, -1);
 
     cfg = virQEMUDriverGetConfig(driver);
     if ((compressed = qemuSaveImageGetCompressionProgram(cfg->saveImageFormat,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index de1146251d..7ea0bdaa39 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7839,13 +7839,9 @@ qemuProcessStart(virConnectPtr conn,
         if (incoming->deferredURI &&
             qemuMigrationDstRun(driver, vm, incoming->deferredURI, asyncJob) < 0)
             goto stop;
-    } else {
-        /* Refresh state of devices from QEMU. During migration this happens
-         * in qemuMigrationDstFinish to ensure that state information is fully
-         * transferred. */
-        if (qemuProcessRefreshState(driver, vm, asyncJob) < 0)
-            goto stop;
     }
+    if (qemuProcessRefreshState(driver, vm, asyncJob) < 0)
+        goto stop;
 
     if (qemuProcessFinishStartup(driver, vm, asyncJob,
                                  !(flags & VIR_QEMU_PROCESS_START_PAUSED),
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index f086c2dd4b..b419fe6b58 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -4173,6 +4173,10 @@ static const vshCmdOptDef opts_save[] = {
      .type = VSH_OT_BOOL,
      .help = N_("display the progress of save")
     },
+    {.name = "pauseaftersave",
+     .type = VSH_OT_BOOL,
+     .help = N_("set domain to be paused after save")
+    },
     {.name = NULL}
 };
 
@@ -4206,6 +4210,8 @@ doSave(void *opaque)
         flags |= VIR_DOMAIN_SAVE_RUNNING;
     if (vshCommandOptBool(cmd, "paused"))
         flags |= VIR_DOMAIN_SAVE_PAUSED;
+    if (vshCommandOptBool(cmd, "pauseaftersave"))
+       flags |= VIR_DOMAIN_PAUSE_AFTER_SAVE;
 
     if (vshCommandOptStringReq(ctl, cmd, "xml", &xmlfile) < 0)
         goto out;

在libvirt-domain.h文件中增加VIR_DOMAIN_PAUSE_AFTER_SAVE 标志位;

如果想要支持virsh命令的话,则需要在virsh-domain.c文件中增加pauseaftersave参数,这样在执行virsh save的时候,就可以加上--pauseaftersave的标志位了!

效果测试

[root@localhost xml]# virsh start centos
Domain 'centos' started

[root@localhost xml]# virsh save centos test.mem --pauseaftersave

Domain 'centos' saved to test.mem

[root@localhost xml]# virsh list 
 Id   Name     State
-----------------------
 2    centos   paused

此时从虚拟机内部来看,业务是处于暂停的状态。

root@localhost xml]# virsh resume centos
Domain 'centos' resumed

[root@localhost xml]# virsh list 
 Id   Name     State
------------------------
 2    centos   running

执行virsh resume命令之后,云主机业务继续运行。

virsh save --help
  NAME
    save - save a domain state to a file

  SYNOPSIS
    save <domain> <file> [--bypass-cache] [--xml <string>] [--running] [--paused] [--verbose] [--pauseaftersave]

  DESCRIPTION
    Save the RAM state of a running domain.

  OPTIONS
    [--domain] <string>  domain name, id or uuid
    [--file] <string>  where to save the data
    --bypass-cache   avoid file system cache when saving
    --xml <string>   filename containing updated XML for the target
    --running        set domain to be running on restore
    --paused         set domain to be paused on restore
    --verbose        display the progress of save
    --pauseaftersave  set domain to be paused after save

执行virsh save --help,可以看到--pauseaftersave参数的提示信息

调用python API接口,代码如下:

#!/usr/bin/env python3
"""
Save all currently running domU's into DIR.
DIR must exist and be writable by this process.
"""

import libvirt
import os
from argparse import ArgumentParser


parser = ArgumentParser(description=__doc__)
parser.add_argument("dir")
args = parser.parse_args()

try:
    conn = libvirt.open("qemu:///system")
except libvirt.libvirtError:
    print('Failed to open connection to the hypervisor')
    exit(1)

doms = conn.listDomainsID()
for id in doms:
    if id == 0:
        continue
    dom = conn.lookupByID(id)
    print("Saving %s[%d] ... " % (dom.name(), id))
    import pdb; pdb.set_trace()
    #path = os.path.join(args.dir, dom.name())
    path = args.dir
    ret = dom.saveFlags(path, flags=8)
    if ret == 0:
        print("done")
    else:
        print("error %d" % ret)

执行效果和virsh一样,因为内部调用的都是同一个接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值