自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

OpenStack Create Snapshot源碼流程分析,理解創(chuàng)建快照的本質(zhì)

云計(jì)算 OpenStack
筆者以一個(gè)普通用戶的角度,在實(shí)際應(yīng)用的過程中不斷深入對看OpenStack的理解。在遇到故障時(shí),通過對源碼流程的分析,來探求問題出現(xiàn)的原因是知道在操作上還是系統(tǒng)上。本篇博文主要針對作者對創(chuàng)建快照過程(Create Snapshot)的源代碼流程的分析,走出了之前的認(rèn)知誤區(qū),理解了目前OpenStack創(chuàng)建快照過程的實(shí)質(zhì)。

編者的話

筆者以一個(gè)普通用戶的角度,在實(shí)際應(yīng)用的過程中不斷深入對看OpenStack的理解。在遇到故障時(shí),通過對源碼流程的分析,來探求問題出現(xiàn)的原因是知道在操作上還是系統(tǒng)上。本篇博文主要針對作者對創(chuàng)建快照過程(Create Snapshot)的源代碼流程的分析,走出了之前的認(rèn)知誤區(qū),理解了目前OpenStack創(chuàng)建快照過程的實(shí)質(zhì)。

[[126282]]

背景:

一直以為OpenStack的創(chuàng)建快照的操作是在線創(chuàng)建快照(live snapshot), 并且應(yīng)該是增量的快照,即利用virsh或者qemu的live snapshot來實(shí)現(xiàn)的:

virsh snapshot-create-as --live ....

后來發(fā)現(xiàn)快照和原始鏡像之間并沒有依賴關(guān)系,感覺OpenStack還做的挺好的,自動解決了增量快照和原始鏡像之間的依賴關(guān)系;

但是后來又發(fā)現(xiàn)做快照的時(shí)候虛擬機(jī)竟然會shutoff, 就感覺不對了,于是分析了下源碼。

源代碼流程分析

1 nova/compute/api.py

  1. # NOTE(melwitt): We don't check instance lock for snapshot because lock is 
  2. # intended to prevent accidental change/delete of instances 
  3. @wrap_check_policy 
  4. @check_instance_cell 
  5. @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED, 
  6. vm_states.PAUSED, vm_states.SUSPENDED]) 
  7. def snapshot(self, context, instance, name, extra_properties=None): 
  8. """Snapshot the given instance. 
  9.  
  10. :param instance: nova.db.sqlalchemy.models.Instance 
  11. :param name: name of the snapshot 
  12. :param extra_properties: dict of extra image properties to include 
  13. when creating the image. 
  14. :returns: A dict containing image metadata 
  15. ""
  16. #調(diào)用glance api創(chuàng)建image entry,為后將snapshot上傳為鏡像做準(zhǔn)備,雖然鏡像和snapshot在可以上傳到glance作為鏡像啟動虛擬機(jī), 
  17. #但是為了區(qū)分二者的不同,glance將鏡像和snapshot標(biāo)記衛(wèi)不同的類型:type=image 和 type=snapshot 
  18. image_meta = self._create_image(context, instance, name, 
  19. 'snapshot'
  20. extra_properties=extra_properties) 
  21.  
  22. # NOTE(comstud): Any changes to this method should also be made 
  23. # to the snapshot_instance() method in nova/cells/messaging.py 
  24. # 將任務(wù)狀態(tài)(task state) 設(shè)置為:image_snapshot_pending 
  25. instance.task_state = task_states.IMAGE_SNAPSHOT_PENDING 
  26. instance.save(expected_task_state=[None]) 
  27. #通過rpc調(diào)用nova/compute/rpcapi.py的snapshot_instance函數(shù) 
  28. self.compute_rpcapi.snapshot_instance(context, instance, 
  29. image_meta['id  

 

2 nova/compute/rpcapi.py

  1.  #梳理下流程: (1)用戶發(fā)起create snapshot的請求; (2)nova-api服務(wù)接收到這個(gè)請求并進(jìn)行前期處理,即3.1中代碼的處理流程; 
  2. 3)真正的snapshot操作是需要在nova-compute節(jié)點(diǎn)上執(zhí)行的,所以nova-api需要向nova-compute發(fā)送message 
  3. #由于OpenStack環(huán)境中會有很多個(gè)nova-compute,所以需要通過server=_compute_host(None, instance)來獲取虛擬機(jī)所在的host,并向其發(fā)送message。 
  4. def snapshot_instance(self, ctxt, instance, image_id): 
  5. version = '3.0' 
  6. cctxt = self.client.prepare(server=_compute_host(None, instance), 
  7. version=version) 
  8. cctxt.cast(ctxt, 'snapshot_instance'
  9. instance=instance, 
  10. image_id=image_id) 
  11.  
  12. 3 nova/virt/libvirt/driver.py 
  13.  
  14. def snapshot(self, context, instance, image_id, update_task_state): 
  15. """Create snapshot from a running VM instance. 
  16.  
  17. This command only works with qemu 0.14
  18. ""
  19. try
  20. virt_dom = self._get_domain(instance) 
  21. except exception.InstanceNotFound: 
  22. raise exception.InstanceNotRunning(instance_id=instance['uuid']) 
  23.  
  24. base_image_ref = instance['image_ref'
  25.  
  26. base = compute_utils.get_image_metadata( 
  27. context, self._image_api, base_image_ref, instance) 
  28.  
  29. snapshot = self._image_api.get(context, image_id) 
  30.  
  31. disk_path = libvirt_utils.find_disk(virt_dom) 
  32. source_format = libvirt_utils.get_disk_type(disk_path) 
  33.  
  34. image_format = CONF.libvirt.snapshot_image_format or source_format 
  35.  
  36. # NOTE(bfilippov): save lvm and rbd as raw 
  37. if image_format == 'lvm' or image_format == 'rbd'
  38. image_format = 'raw' 
  39.  
  40. metadata = self._create_snapshot_metadata(base, 
  41. instance, 
  42. image_format, 
  43. snapshot['name']) 
  44.  
  45. snapshot_name = uuid.uuid4().hex 
  46.  
  47. state = LIBVIRT_POWER_STATE[virt_dom.info()[0]] 
  48.  
  49. # NOTE(rmk): Live snapshots require QEMU 1.3 and Libvirt 1.0.0
  50. # These restrictions can be relaxed as other configurations 
  51. # can be validated. 
  52. # NOTE(dgenin): Instances with LVM encrypted ephemeral storage require 
  53. # cold snapshots. Currently, checking for encryption is 
  54. # redundant because LVM supports only cold snapshots. 
  55. # It is necessary in case this situation changes in the 
  56. # future. 
  57. #這里需要注意,解釋了為啥現(xiàn)在是cold snapshot而不是live snapshot: 
  58. # 有人提過live snapshot的bug,社區(qū)認(rèn)為live snapshot目前不穩(wěn)定,所以默認(rèn)條件下采用cold snapshot,并且是通過硬編碼來實(shí)現(xiàn)的 
  59. # 看下面這個(gè)判斷條件,成立的時(shí)候?qū)ive_snapshot = true,其中MIN_LIBVIRT_LIVESNAPSHOT_VERSION=1.3.0, 其實(shí)現(xiàn)在libvirt的***版本 
  60. # 才到1.2.11, 所以這個(gè)live_snapshot的條件不滿足,就變成了cold_snapshot 
  61. if (self._host.has_min_version(MIN_LIBVIRT_LIVESNAPSHOT_VERSION, 
  62. MIN_QEMU_LIVESNAPSHOT_VERSION, 
  63. REQ_HYPERVISOR_LIVESNAPSHOT) 
  64. and source_format not in ('lvm''rbd'
  65. and not CONF.ephemeral_storage_encryption.enabled): 
  66. live_snapshot = True 
  67. # Abort is an idempotent operation, so make sure any block 
  68. # jobs which may have failed are ended. This operation also 
  69. # confirms the running instance, as opposed to the system as a 
  70. # whole, has a new enough version of the hypervisor (bug 1193146). 
  71. try
  72. virt_dom.blockJobAbort(disk_path, 0
  73. except libvirt.libvirtError as ex: 
  74. error_code = ex.get_error_code() 
  75. if error_code == libvirt.VIR_ERR_CONFIG_UNSUPPORTED: 
  76. live_snapshot = False 
  77. else
  78. pass 
  79. else
  80. live_snapshot = False 
  81.  
  82. # NOTE(rmk): We cannot perform live snapshots when a managedSave 
  83. # file is present, so we will use the cold/legacy method 
  84. for instances which are shutdown. 
  85. if state == power_state.SHUTDOWN: 
  86. live_snapshot = False 
  87.  
  88. # NOTE(dkang): managedSave does not work for LXC 
  89. #注意這里,如果live_snashot目前是false,所以在做snapshot之前先要執(zhí)行: 
  90. #(1)_detach_pci_devices, 卸載虛擬機(jī)掛載的pci設(shè)備,比如數(shù)據(jù)盤 
  91. #(2) self._detach_sriov_ports, 卸載虛擬機(jī)掛載的SRIOV設(shè)備,比如支持SRIOV的網(wǎng)卡設(shè)備 
  92. if CONF.libvirt.virt_type != 'lxc' and not live_snapshot: 
  93. if state == power_state.RUNNING or state == power_state.PAUSED: 
  94. self._detach_pci_devices(virt_dom, 
  95. pci_manager.get_instance_pci_devs(instance)) 
  96. self._detach_sriov_ports(instance, virt_dom) 
  97. virt_dom.managedSave(0
  98. #判斷虛擬機(jī)的后端存儲是什么,不同的后端存儲做snapshot是不同的,本地文件系統(tǒng)的化,默認(rèn)qcow2 
  99. snapshot_backend = self.image_backend.snapshot(instance, 
  100. disk_path, 
  101. image_type=source_format) 
  102.  
  103. if live_snapshot: 
  104. LOG.info(_LI("Beginning live snapshot process"), 
  105. instance=instance) 
  106. else
  107. LOG.info(_LI("Beginning cold snapshot process"), 
  108. instance=instance) 
  109. #更新任務(wù)的狀態(tài)為:image_pending_upload, 大家都知道做完snapshot要上傳 
  110. update_task_state(task_state=task_states.IMAGE_PENDING_UPLOAD) 
  111. #目前做快照的過程是: 
  112. #(1)現(xiàn)在../data/nova/instance/snapshots目錄下生成臨時(shí)目錄,比如nova/instances/snapshots/tmptHr585 
  113. #(2)然后將快照生成到這個(gè)目錄,具體參見snapshot_backend.snapshot_extract(out_path, image_format)這個(gè)函數(shù) 
  114. #(3)生成完成后,通過glance api上傳,具體參見 self._image_api.update 
  115. snapshot_directory = CONF.libvirt.snapshots_directory 
  116. fileutils.ensure_tree(snapshot_directory) 
  117. with utils.tempdir(dir=snapshot_directory) as tmpdir: 
  118. try
  119. out_path = os.path.join(tmpdir, snapshot_name) 
  120. if live_snapshot: 
  121. # NOTE(xqueralt): libvirt needs o+x in the temp directory 
  122. os.chmod(tmpdir, 0o701) 
  123. self._live_snapshot(context, instance, virt_dom, disk_path, 
  124. out_path, image_format, base) 
  125. else
  126. #這個(gè)函數(shù)實(shí)際執(zhí)行了一條命令: qemu-img convert -f qcow2 -O qcow2 disk_path out_path,算是生成了快照 
  127. snapshot_backend.snapshot_extract(out_path, image_format) 
  128. finally
  129. new_dom = None 
  130. # NOTE(dkang): because previous managedSave is not called 
  131. for LXC, _create_domain must not be called. 
  132. if CONF.libvirt.virt_type != 'lxc' and not live_snapshot: 
  133. if state == power_state.RUNNING: 
  134. new_dom = self._create_domain(domain=virt_dom) ##恢復(fù)做快照之前虛擬機(jī)的狀態(tài) 
  135. elif state == power_state.PAUSED: 
  136. new_dom = self._create_domain(domain=virt_dom, 
  137. launch_flags=libvirt.VIR_DOMAIN_START_PAUSED) 
  138. if new_dom is not None: 
  139. self._attach_pci_devices(new_dom, 
  140. pci_manager.get_instance_pci_devs(instance)) 
  141. self._attach_sriov_ports(context, instance, new_dom) 
  142. LOG.info(_LI("Snapshot extracted, beginning image upload"), 
  143. instance=instance) 
  144.  
  145. # Upload that image to the image service 
  146.  
  147. update_task_state(task_state=task_states.IMAGE_UPLOADING, 
  148. expected_state=task_states.IMAGE_PENDING_UPLOAD) 
  149. with libvirt_utils.file_open(out_path) as image_file: ###將生成的快照上傳到glance 
  150. self._image_api.update(context, 
  151. image_id, 
  152. metadata, 
  153. image_file) 
  154. LOG.info(_LI("Snapshot image upload complete"), 
  155. instance=instance)  

結(jié)論:

目前OpenStack默認(rèn)的快照方式都是cold snapshot, 首先先關(guān)機(jī),其次執(zhí)行如下命令生成一個(gè)鏡像文件,再次開機(jī),***再調(diào)用glance api將鏡像上傳。

  1. qemu-img convert -f qcow2 -O qcow2 <disk_path> <out_path> 

所以目前并不是真正意義的快照,其實(shí)和關(guān)閉虛擬機(jī),拷貝一份,再上傳沒有本質(zhì)區(qū)別。

博文出處:http://blog.chinaunix.net/uid-20940095-id-4752643.html

責(zé)任編輯:Ophira 來源: ChinaUnix博客
相關(guān)推薦

2012-11-22 10:11:16

LispLisp教程

2014-03-12 10:19:54

iOS對象

2016-10-26 20:49:24

ReactJavascript前端

2021-09-10 06:50:03

Node.jsSocket端口

2021-03-11 08:10:48

JVM對象的創(chuàng)建School

2021-09-08 10:47:33

Flink執(zhí)行流程

2024-12-03 15:15:22

2025-04-22 08:21:10

2025-04-28 02:00:00

2021-08-26 11:21:34

技術(shù)代碼計(jì)算

2009-09-15 15:09:50

Linq本質(zhì)

2020-07-13 09:09:23

Sentinel源碼Bucket

2017-02-27 11:48:58

JVM源碼分析Java

2009-12-14 18:04:38

Linux命令創(chuàng)建快照

2009-09-15 14:58:26

Linq查詢本質(zhì)

2017-03-16 11:39:33

Openstack源碼姿勢

2011-05-24 10:24:29

創(chuàng)建與使用VMware

2014-05-12 16:40:13

Linux命令快照

2021-09-30 07:36:51

AndroidViewDraw

2016-12-19 15:09:02

Jedis源碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號