当前位置:   article > 正文

利用qemu-guest-agent冻结文件系统_qemu-guest-agent centos8

qemu-guest-agent centos8

转载:www.silenceli.com?p=250

本文将介绍:

  1. qemu-guest-agent是什么?
  2. 为什么使用qemu-guest-agent
  3. 如何利用qemu-guest-agent冻结文件系统?
  4. qemu-ga与openstack的结合

What is qemu-ga

我个人认为qemu-ga是在虚拟机中安装的一个agent,宿主机host通过通道(unix socket)与虚拟机vm内部的agent进行通信,这样宿主机就有了一种从外部控制/获取虚拟机的手段。比如:host可以向vm下发执行修改 hostname的指令,或者获取vm内所有进程信息的指令。

qemu-ga时刻监听这个unix socket,一旦发现有指令发送来,分析该指令,并执行,通过unix socket返回执行结果。

通过在虚拟机内部预装qemu-ga,云平台对虚拟机的控制能力显著加强,举个例子:阿里云中有个产品叫“云盾 安骑士”,该产品能够自动修复软件安全漏洞、查杀木马、实时告警等等。其本质上来说,也是在vm中安装了某种agent。

Why use qemu-ga

目前市面上的开源agent产品也有不少,最有名的是qemu-ga和ovirt-guest-agent,通过比较发现

qemu-gaovirt-ga
开发语言C语言python
通道协议qmp协议(QEMU Machine Protocol)自定义
提供商QEMU官方Red Hat
操作系统支持windows/linux
对于linux直接提供rpm包
windows/linux
对于linux直接提供rpm包
支持功能guest-set-vcpus
guest-get-vcpus
guest-network-get-interfaces
guest-suspend-hybrid
guest-suspend-ram
guest-suspend-disk
guest-fstrim
guest-fsfreeze-thaw
guest-fsfreeze-freeze
guest-fsfreeze-status
guest-file-flush
guest-file-seek
guest-file-seek
guest-file-read
guest-file-close
guest-file-open
guest-shutdown
guest-info
guest-set-time
guest-get-time
guest-ping
guest-sync
guest-sync-delimited
1. information(吐出的信息,定期吐出可配置)
主机名
操作系统及版本
IP地址
已安装的软件
可用的内存
已登录的用户
活动用户(不详)2. 被触发的消息,即vm内部出现某种情况后,ovirt-ga将发送消息给host
开机
心跳(定期发送)
活动用户切换
windows锁屏
windows log off
windows log on
ovirt-ga被卸载

3.执行的命令
锁屏
自动登录
自动log off
关机

可扩展性提供专门的方式,每一个功能需要增加一个对应的文件直接修改ovirt-ga源码,通常修改
GuestAgentLinux2.py
OVirtAgentLogic.py
openstack兼容性openstack支持
相关bp:https://blueprints.launchpad.net/nova/+spec/qemu-guest-agent-support
https://blueprints.launchpad.net/nova/+spec/quiesced-image-snapshots-with-qemu-guest-agent
openstack不支持,需要手动修改openstack代码

通过对比,qemu-ga的优势是qemu官方出品,与openstack深度结合,而且协议规范,代码规范,添加新的功能时,也相对独立,同时原生的qemu-ga就支持freezefs功能,这些优势都是ovirt-guest-agent无法比拟的。

how to use qemu-ga

  1. 在虚拟机中安装qemu-ga,针对centos 6.X
    1
    
    yum install qemu-guest-agent
  2. 修改安装后的qemu-ga配置文件
    1
    2
    3
    4
    5
    6
    7
    
    #修改/etc/sysconfig/qemu-ga文件
    将 
    # Enable fsfreeze hook. See the --fsfreeze-hook option in "qemu-ga --help".
    FSFREEZE_HOOK_ENABLE=0
    改为
    # Enable fsfreeze hook. See the --fsfreeze-hook option in "qemu-ga --help".
    FSFREEZE_HOOK_ENABLE=1
    1
    2
    3
    4
    5
    
    #修改/etc/sysconfig/qemu-ga,注释掉BLACKLIST_RPC这一行,将所有功能开放
    将
    BLACKLIST_RPC="guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush"
    改为
    #BLACKLIST_RPC="guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush"
  3. 将虚拟机关机,在虚拟机配置文件libvirt.xml中的<devices>下面添加下述配置,并重新启动虚拟机
    1
    2
    3
    4
    
    <channel type='unix'>
       <source mode='bind' path='/var/lib/libvirt/qemu/f16x86_64.agent'/>
       <target type='virtio' name='org.qemu.guest_agent.0'/>
    </channel>
  4. 测试是否正常:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    #得到虚拟机对应的domain id
    [root@node-12 ~]# virsh list
     Id    名称                         状态
    ----------------------------------------------------
     90    instance-0000209f              running
     
    #使用命令进行测试
    [root@node-12 ~]# virsh qemu-agent-command 90 '{"execute":"guest-info"}'
    {"return":{"version":"0.12.1","supported_commands":[{"enabled":true,"name":"guest-set-vcpus"},{"enabled":true,"name":"guest-get-vcpus"},{"enabled":true,"name":"guest-network-get-interfaces"},{"enabled":true,"name":"guest-suspend-hybrid"},{"enabled":true,"name":"guest-suspend-ram"},{"enabled":true,"name":"guest-suspend-disk"},{"enabled":true,"name":"guest-fstrim"},{"enabled":true,"name":"guest-fsfreeze-thaw"},{"enabled":true,"name":"guest-fsfreeze-freeze"},{"enabled":true,"name":"guest-fsfreeze-status"},{"enabled":true,"name":"guest-file-flush"},{"enabled":true,"name":"guest-file-seek"},{"enabled":true,"name":"guest-file-write"},{"enabled":true,"name":"guest-file-read"},{"enabled":true,"name":"guest-file-close"},{"enabled":true,"name":"guest-file-open"},{"enabled":true,"name":"guest-shutdown"},{"enabled":true,"name":"guest-info"},{"enabled":true,"name":"guest-set-time"},{"enabled":true,"name":"guest-get-time"},{"enabled":true,"name":"guest-ping"},{"enabled":true,"name":"guest-sync"},{"enabled":true,"name":"guest-sync-delimited"}]}}
  5. freeze文件系统的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#直接用virsh命令,freeze文件系统
[root@node-12 ~]# virsh qemu-agent-command 90 '{"execute":"guest-fsfreeze-freeze"}'
{"return":1}
 
#freeze后,可以查询当前虚拟机文件系统的状态,表明是frozen
[root@node-12 ~]# virsh qemu-agent-command 90 '{"execute":"guest-fsfreeze-status"}'
{"return":"frozen"}
 
#thaw(解封)文件系统
[root@node-12 ~]# virsh qemu-agent-command 90 '{"execute":"guest-fsfreeze-thaw"}'
{"return":1}
 
#thaw后,文件系统为解封状态
[root@node-12 ~]# virsh qemu-agent-command 90 '{"execute":"guest-fsfreeze-status"}'
{"return":"thawed"}

The integration of qemu-ga and openstack

首先需要在openstack镜像中增加metadata信息:hw_qemu_guest_agent=yes,命令如下:

1
nova image-meta 6410b84d-a473-4ece-83e5-09848a545645 set hw_qemu_guest_agent=yes

这样创建的虚拟机就会增加qemu-ga通道

目前和qemu-ga在openstack(kilo)中,只被用在创建volume虚拟机的snapshot时,封锁文件系统,保证创建的 snapshot的数据一致性。在def snapshot_volume_backed(nova/compute/api.py中),此函数是nova api执行的,详见下面的代码,我们只关注封锁文件系统,解除封锁文件系统与之类似,留给朋友们自己分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  1. # NOTE(melwitt): We don't check instance lock for snapshot because lock is
  2. # intended to prevent accidental change/delete of instances
  3. @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED])
  4. def snapshot_volume_backed(self, context, instance, image_meta, name,
  5. extra_properties=None):
  6. """Snapshot the given volume-backed instance.
  7.  
  8. :param instance: nova.objects.instance.Instance object
  9. :param image_meta: metadata for the new image
  10. :param name: name of the backup or snapshot
  11. :param extra_properties: dict of extra image properties to include
  12.  
  13. :returns: the new image metadata
  14. """
  15. image_meta['name'] = name
  16. image_meta['is_public'] = False
  17. properties = image_meta['properties']
  18. if instance.root_device_name:
  19. properties['root_device_name'] = instance.root_device_name
  20. properties.update(extra_properties or {})
  21.  
  22. quiesced = False
  23. if instance.vm_state == vm_states.ACTIVE:
  24. try:
  25. #封锁文件系统
  26. self.compute_rpcapi.quiesce_instance(context, instance)
  27. quiesced = True
  28. except (exception.InstanceQuiesceNotSupported,
  29. exception.NovaException, NotImplementedError) as err:
  30. if strutils.bool_from_string(properties.get(
  31. 'os_require_quiesce')):
  32. raise
  33. else:
  34. LOG.info(_LI('Skipping quiescing instance: '
  35. '%(reason)s.'), {'reason': err},
  36. context=context, instance=instance)
  37.  
  38. bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
  39. context, instance.uuid)
  40.  
  41. mapping = []
  42. for bdm in bdms:
  43. if bdm.no_device:
  44. continue
  45.  
  46. if bdm.is_volume:
  47. # create snapshot based on volume_id
  48. volume = self.volume_api.get(context, bdm.volume_id)
  49. # NOTE(yamahata): Should we wait for snapshot creation?
  50. # Linux LVM snapshot creation completes in
  51. # short time, it doesn't matter for now.
  52. name = _('snapshot for %s') % image_meta['name']
  53. #创建volume的snapshot
  54. snapshot = self.volume_api.create_snapshot_force(
  55. context, volume['id'], name, volume['display_description'])
  56. mapping_dict = block_device.snapshot_from_bdm(snapshot['id'],
  57. bdm)
  58. mapping_dict = mapping_dict.get_image_mapping()
  59. else:
  60. mapping_dict = bdm.get_image_mapping()
  61.  
  62. mapping.append(mapping_dict)
  63.  
  64. #解封文件系统
  65. if quiesced:
  66. self.compute_rpcapi.unquiesce_instance(context, instance, mapping)
  67.  
  68. # NOTE (ndipanov): Remove swap/ephemerals from mappings as they will be
  69. # in the block_device_mapping for the new image.
  70. image_mappings = properties.get('mappings')
  71. if image_mappings:
  72. properties['mappings'] = [m for m in image_mappings
  73. if not block_device.is_swap_or_ephemeral(
  74. m['virtual'])]
  75. if mapping:
  76. properties['block_device_mapping'] = mapping
  77. properties['bdm_v2'] = True
  78.  
  79. for attr in ('status', 'location', 'id', 'owner'):
  80. image_meta.pop(attr, None)
  81.  
  82. # the new image is simply a bucket of properties (particularly the
  83. # block device mapping, kernel and ramdisk IDs) with no image data,
  84. # hence the zero size
  85. image_meta['size'] = 0
  86.  
  87. return self.image_api.create(context, image_meta)

进一步封锁文件系统的代码,进入到compute/rpcapi.py中的    def quiesce_instance(self, ctxt, instance)该函数主要发送封锁文件系统指令(rpc call)给nova compute:

1
2
3
4
5
6
  1. def quiesce_instance(self, ctxt, instance):
  2. version = self._compat_ver('4.0', '3.39')
  3. cctxt = self.client.prepare(server=_compute_host(None, instance),
  4. version=version)
  5. #向消息队列中发送封锁文件系统的指令,此函数最终由compute/manager.py中的def quiesce_instance执行
  6. return cctxt.call(ctxt, 'quiesce_instance', instance=instance)

接下来调用进入了nova compute,由compute/manager.py继续处理:

1
2
3
4
5
6
7
8
9
10
11
  1. @wrap_exception()
  2. def quiesce_instance(self, context, instance):
  3. """Quiesce an instance on this host."""
  4. context = context.elevated()
  5. #通过instance得到instance所使用的image信息
  6. image_ref = instance.image_ref
  7. #通过image信息得到image保存的metadata信息,因为凡是支持qemu-ga的,对应的image都需要有hw_qemu_guest_agent=yes的metedata信息
  8. image_meta = compute_utils.get_image_metadata(
  9. context, self.image_api, image_ref, instance)
  10. #调用具体的driver(比如libvirt,vmware,xen等等)来实现
  11. self.driver.quiesce(context, instance, image_meta)

继续,只有libvirt支持该功能,代码推进到virt/libvirt/driver.py的def quiesce函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  1. def quiesce(self, context, instance, image_meta):
  2. """Freeze the guest filesystems to prepare for snapshot.
  3.  
  4. The qemu-guest-agent must be setup to execute fsfreeze.
  5. """
  6. #继续调用
  7. self._set_quiesced(context, instance, image_meta, True)
  8.  
  9.  
  10. def _set_quiesced(self, context, instance, image_meta, quiesced):
  11. #判断是否支持封锁文件系统的操作,需要满足3点
  12. #1.虚拟机类型是qemu/kvm
  13. #2.qemu版本必须大于1.2.5
  14. #3.image_meta中必须有hw_qemu_guest_agent=yes
  15. supported, reason = self._can_quiesce(image_meta)
  16. #不支持,就抛异常
  17. if not supported:
  18. raise exception.InstanceQuiesceNotSupported(
  19. instance_id=instance.uuid, reason=reason)
  20.  
  21. try:
  22. domain = self._host.get_domain(instance)
  23. if quiesced:
  24. #调用libvirt库函数,封锁文件系统。类似于执行了virsh qemu-agent-command 90 '{"execute":"guest-fsfreeze-freeze"}'
  25. domain.fsFreeze()
  26. else:
  27. #调用libvirt库函数,解除文件系统封锁。类似于执行了virsh qemu-agent-command 90 '{"execute":"guest-fsfreeze-thaw"}'
  28. domain.fsThaw()
  29. except libvirt.libvirtError as ex:
  30. error_code = ex.get_error_code()
  31. msg = (_('Error from libvirt while quiescing %(instance_name)s: '
  32. '[Error Code %(error_code)s] %(ex)s')
  33. % {'instance_name': instance.name,
  34. 'error_code': error_code, 'ex': ex})
  35. raise exception.NovaException(msg)

 

reference

[1]  http://www.ovirt.org/Guest_Agent  ovirt-guest-agent介绍

[2] http://wiki.qemu.org/Features/QAPI/GuestAgent qemu-ga介绍

[3] http://wiki.qemu.org/QMP qemu-ga的qmp协议介绍

[4] https://blueprints.launchpad.net/nova/+spec/quiesced-image-snapshots-with-qemu-guest-agent 创建volume虚拟机snapshot时,使用qemu-ga封锁文件系统的bp

[5] https://blueprints.launchpad.net/nova/+spec/qemu-guest-agent-support 在nova中增加支持qemu-ga的bp

查看原文:http://www.zoues.com/index.php/2015/10/13/qemu-guest-agent/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/217506
推荐阅读
相关标签
  

闽ICP备14008679号