1. 程式人生 > >OpenStack快照分析:(三)從磁碟啟動雲主機離線(線上)快照分析

OpenStack快照分析:(三)從磁碟啟動雲主機離線(線上)快照分析

1.1.nova-api處理過程

磁碟啟動的雲主機在做離線快照時,還是首先是nova-api接收請求,函式入口和前述一樣,還是nova/api/openstack/compute/servers.py/ServersController._action_create_image下面一起來看看:

@wsgi.response(202) @extensions.expected_errors((400, 403, 404, 409)) # 定義關聯的API介面 @wsgi.action('createImage') @common.check_snapshots_enabled @validation.schema

(schema_servers.create_image, '2.0', '2.0') @validation.schema(schema_servers.create_image, '2.1') def _action_create_image(self, req, id, body): """Snapshot a server instance.""" # req中獲取請求的上下文,並驗證執行許可權context = req.environ['nova.context'] context.can(server_policies.SERVERS % 'create_image')
# body中解析出傳遞的引數,快照名稱及屬性資訊 entity = body["createImage"] image_name = common.normalize_name(entity["name"]) metadata = entity.get('metadata', {}) snapshot_id = entity.get("snapshot_id", None) # Starting from microversion 2.39 we don't check quotas on createImage if api_version_request.is_supported(req
, max_version=api_version_request.MAX_IMAGE_META_PROXY_API_VERSION): # 檢查快照屬性的相關配置資訊 common.check_img_metadata_properties_quota(context, metadata) instance = self._get_server(context, req, id) snapshot = snapshot_current(context, instance, self.compute_rpcapi) if snapshot:# if there are snapshots, then create an image with snashots. if not snapshot_id: snapshot_id = snapshot["id"] image = snapshot_create_image(context, snapshot_id, instance, self.compute_rpcapi, entity) else: #從資料庫中獲取例項物件(InstanceV2)及塊裝置對映列表 bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(context, instance.uuid) # 判斷例項是映象啟動還是磁碟啟動if compute_utils.is_volume_backed_instance(context, instance, bdms): # 校驗執行許可權 context.can(server_policies.SERVERS % 'create_image:allow_volume_backed') # 這裡執行的是磁碟啟動方式的快照,傳遞的引數包括: # 1、關於許可權的上下文context # 2、虛擬機器的例項物件instance # 3、快照的名稱image_name # 本章節講的磁碟啟動的雲主機快照就是進入該分支進行操作。 image = self.compute_api.snapshot_volume_backed(contextinstanceimage_nameextra_properties=metadata) else: # 這裡是映象啟動的雲主機快照的入口,即上節內容 image = self.compute_api.snapshot(context, instance, image_name, extra_properties=metadata) if api_version_request.is_supported(req, '2.45'): return {'image_id': image['id']} # build location of newly-created image entity image_id = str(image['id']) image_ref = glance.generate_image_url(image_id) resp = webob.Response(status_int=202) resp.headers['Location'] = image_ref return resp

可以看到,執行磁碟啟動雲主機快照時,實際走的是“compute_api.snapshot_volume_backed”,下面對這部分程式碼具體分析,程式碼位置:nova/compute/api.py/API.snapshot_volume_backed

@check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED, vm_states.SUSPENDED]) def snapshot_volume_backed(self, context, instance, name, extra_properties=None): """Snapshot the given volume-backed instance.從例項的system_metadata生成映象屬性(排除不可繼承屬性),如下:# { #u'min_disk': u'20', #'is_public': False, #'min_ram': u'0', #'properties': { #'base_image_ref': u'' #}, #'name': u'snapshot1' # }

:param instance: nova.objects.instance.Instance object :param name: name of the backup or snapshot :param extra_properties: dict of extra image properties to include :returns: the new image metadata """ # 獲取例項的metadata屬性image_meta = self._initialize_instance_snapshot_metadata(instance, name, extra_properties)image_meta['size'] = 0 # 清除映象metadata屬性中的container_formatdisk_forma屬性for attr in ('container_format', 'disk_format'): image_meta.pop(attr, None) properties = image_meta['properties'] # clean properties before filling,清除properties屬性裡面的'block_device_mapping', 'bdm_v2', 'root_device_name'相關屬性值for key in ('block_device_mapping', 'bdm_v2', 'root_device_name'): properties.pop(key, None) # 將例項中的‘root_device_name’屬性更新到properties屬性裡,image_meta的最終內容如: # { #'name': u'snapshot1', #u'min_ram': u'0', #u'min_disk': u'20', #'is_public': False, #'properties': { #u'base_image_ref': u'', #'root_device_name': u'/dev/vda' #}, #'size': 0 # }if instance.root_device_name: properties['root_device_name'] = instance.root_device_name # 從資料庫中獲取該雲主機所關聯的所有塊裝置,結果會返回一個BlockDeviceMappingList物件 bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(context, instance.uuid) # 接下來開始做快照的操作,注意,雲主機掛在了多少個卷裝置,就要做多少次快照 mapping = []# list of BDM dicts that can go into the image properties # Do some up-front filtering of the list of BDMs from # which we are going to create snapshots. volume_bdms = [] for bdm in bdms: if bdm.no_device: # 對映關係中沒有塊裝置,則忽略此條對映continue if bdm.is_volume: # These will be handled below.此對映包含塊裝置,加入到volume_bdms,準備做快照volume_bdms.append(bdm) else: mapping.append(bdm.get_image_mapping()) # Check limits in Cinder before creating snapshots to avoid going over # quota in the middle of a list of volumes. This is a best-effort check # but concurrently running snapshot requests from the same project # could still fail to create volume snapshots if they go over limit. # 在建立快照之前,需要首先在Cinder中檢查配額限制,以避免超過配額限制if volume_bdms: limits = self.volume_api.get_absolute_limits(context) total_snapshots_used = limits['totalSnapshotsUsed'] max_snapshots = limits['maxTotalSnapshots'] # -1 means there is unlimited quota for snapshots if (max_snapshots > -1 and len(volume_bdms) + total_snapshots_used > max_snapshots): LOG.debug('Unable to create volume snapshots for instance. Currently has %s snapshots, requesting %s new snapshots, with a limit of %s.', total_snapshots_used, len(volume_bdms), max_snapshots, instance=instance) raise exception.OverQuota(overs='snapshots') quiesced = False # 判斷虛擬機器的狀態,如果虛擬機器處於active,則通過rpc通知虛擬機器進入靜默狀態(異常處理省略)if instance.vm_state == vm_states.ACTIVE: LOG.info("Attempting to quiesce instance before volume snapshot.", instance=instance) self.compute_rpcapi.quiesce_instance(context, instance) quiesced = True # 定義一個獲取雲主機上的及具體卷資訊的方法,返回雲主機的卷對映 @wrap_instance_event(prefix='api') def snapshot_instance(self, context, instance, bdms): for bdm in volume_bdms: # create snapshot based on volume_id #根據卷的volume_id從資料庫獲取卷的詳細資訊volume = self.volume_api.get(context, bdm.volume_id) # 組裝出一個貌似是desc的消息,比如快照名稱是snapshot1,則這裡就是snapshot for snapshot1name = _('snapshot for %s') % image_meta['name'] LOG.debug('Creating snapshot from volume %s.', volume['id'], instance=instance) # 呼叫cinderapi create_snapshot_force建立新的卷# “create_snapshot_force”中實際上是通過cinderclient來呼叫volume_snapshots.create # 來發起建立卷的請求,具體是由cinder-volume來完成卷的快照,返回的內容為卷快照的資訊, # 格式如: #{

#'status': u'creating', #'display_name': u'snapshot for snapshot1', #'created_at': u'2016-06-24T09:23:00.517279', #'display_description': u'', #'volume_size': 20, #'volume_id': u'60e16af2-0684-433c-a1b6-c1af1c2523fc', #'progress': None, #'project_id': u'25520b29dce346d38bc4b055c5ffbfcb', #'id': u'cede2421-ea68-4a8e-937d-c27074b9024b', #'size': 20 # } snapshot = self.volume_api.create_snapshot_force( context, volume['id'], name, volume['display_description']) # 接著會根據bdm資訊,來構建快照的dict格式屬性資訊,返回一個BlockDeviceDict物件,屬性如下: # { #'guest_format': None, #'boot_index': 0, #'no_device': None, #'connection_info': None, #'snapshot_id': u'cede2421-ea68-4a8e-937d-c27074b9024b', #'volume_size': 20, #'device_name': u'/dev/vda', #'disk_bus': u'virtio', #'image_id': None, #'source_type': 'snapshot', #'device_type': u'disk', #'volume_id': None, #'destination_type': 'volume', #'delete_on_termination': False # } mapping_dict = block_device.snapshot_from_bdm(snapshot['id'], bdm) # 過濾掉已經在資料庫中存在的欄位 mapping_dict = mapping_dict.get_image_mapping() # 將雲主機所有的對映關係都新增到mapping mapping.append(mapping_dict) return mapping self._record_action_start(context, instance, instance_actions.CREATE_IMAGE) # 呼叫“snapshot_instance”,獲取雲主機所有的mapping關係 mapping = snapshot_instance(self, context, instance, bdms) # 如果此時卷的檔案系統已靜默,這裡則進行解凍處理,實現過程就是通過rpc.case傳送非同步請求給nova-compute # nova-compute接收到訊息後,會等到快照完成後對檔案系統進行解凍(需要agent支援)if quiesced: self.compute_rpcapi.unquiesce_instance(context, instance, mapping) # 更新雲主機metadata資訊中的properties資訊if mapping: properties['block_device_mapping'] = mapping properties['bdm_v2'] = True # 到這一步時,會到新增一條記錄到glance快照(映象)資料庫條目 #(會在Dashboard的映象面板顯示一條名為snapshot1的快照記錄) # 快照的大部分資訊都拷貝至系統盤屬性,這是因為卷快照是可以直接用來啟動雲主機的, # 另外'block_device_mapping'屬性中包含所有的volume裝置快照資訊(如果有的話), # 每個volume裝置快照資訊作為一條記錄,記錄在image_properties資料表; # { 'name': u'snapshot1', 'min_ram': u'0', 'min_disk': u'20', 'is_public': False, 'properties': { 'bdm_v2': True, 'block_device_mapping': [{ 'guest_format': None, 'boot_index': 0, 'no_device': None, 'image_id': None, 'volume_id': None, 'device_name': u'/dev/vda', 'disk_bus': u'virtio', 'volume_size': 20, 'source_type': 'snapshot', 'device_type': u'disk', 'snapshot_id': u'cede2421-ea68-4a8e-937d-c27074b9024b', 'destination_type': 'volume', 'delete_on_termination': False }], 'base_image_ref': u'', 'root_device_name': u'/dev/vda' }, 'size': 0 } return self.image_api.create(context, image_meta)

最後一步通過呼叫image_apicreate來建立image,跟蹤過去實際上就只有一句session.create(context, image_info, data=data),呼叫RESTful API來建立image

至此,nova-api的工作已經做完,總結一下,nov-api主要是 完成了一下工作:

相關推薦

OpenStack快照分析磁碟啟動主機離線(線上)快照分析

1.1.nova-api處理過程 磁碟啟動的雲主機在做離線快照時,還是首先是nova-api接收請求,函式入口和前述一樣,還是nova/api/openstack/compute/servers.py/ServersController._action_create_image,下面一起來看看: @w

零開始學Socket服務端和客戶端簡單通訊

連線上服務端和客戶端之後,我們就要讓他們互動起來了。(到了現在,大家如果對下面程式碼不懂得地方可以去F12跟蹤至原始碼介面檢視,學習就是這樣) 先在服務端編寫傳送函式和接收函式 /// <summary> /// 傳送資料到客戶

OpenStack多節點安裝Glance

上篇文章講述瞭如何安裝Identity service(Keystone),本文將繼續講解如何安裝Glance(映象服務)。 1. 首先先配置兩個客戶端指令碼檔案:admin-openrc and demo-openrc,方便後面執行openstack客戶端命令程式 a

RPG遊戲《黑暗之光》流程介紹與程式碼分析角色控制系統的實現

第三章:角色控制本篇部落格主要對人物移動及其相關操作進行分析,主要包括主角以及鏡頭的移動。在遊戲介面中,我們使用Camera作為視角。為了方便之後判斷當前tag,我們新建一個Tag指令碼,存入一些tag資訊,之後呼叫就不容易出錯using UnityEngine; using

源碼分析系列x264_deblocking_dataflow

像素 色度 結構 inf blank 水平 frame 垂直 左右 http://www.cnblogs.com/xkfz007/articles/2616157.html 去塊濾波(Deblocking)部分關鍵函數 3.1 deblocking_filter_ed

深度學習TensorFlow環境搭建Ubuntu16.04+CUDA8.0+cuDNN7+Anaconda4.4+Python3.6+TensorFlow1.3

缺失 應該 否則 wid -c 方式 *** 也不能 collected   緊接著上一篇的文章《深度學習(TensorFlow)環境搭建:(二)Ubuntu16.04+1080Ti顯卡驅動》,這篇文章,主要講解如何安裝CUDA+CUDNN,不過前提是我們是已經把NVID

【轉】Spring Boot幹貨系列啟動原理解析

無法 time exp 記得 started 打印 ping 正文 exclude 前言 前面幾章我們見識了SpringBoot為我們做的自動配置,確實方便快捷,但是對於新手來說,如果不大懂SpringBoot內部啟動原理,以後難免會吃虧。所以這次博主就跟你們一起一步步揭開

Android 開發安卓常用控制元件以及仿《微門戶》登入介面實現

一、常用控制元件: 1、文字類控制元件 TextView 負責展示文字,非編輯 EditText 可編輯文字控制元件 2、按鈕類控制元件 Button 按鈕 ImageButton 圖片按鈕 RadioButton與RadioGroup 單

OpenStack架構----glance元件

前言: 整個OpenStack是由控制節點,計算節點,網路節點,儲存節點四大部分組成。控制節點的基礎管理服務包含Keystone,Glance,Nova,Neutron,Horizon五個服務,本篇博文將講述galnce元件的部署。Glance:映象管理服務,提供了對虛擬機器部署的時候所能提供的映象的

大資料專案實戰之 --- 某App管理平臺的手機app日誌分析系統

一、建立hive分割槽表 ---------------------------------------------------- 1.建立資料庫 $hive> create database applogsdb; 2.建立分割槽表 編寫指令碼。

Vue路由

(一)基礎介紹 vue-router用來構建SPA <router-link></router-link>或者this.$router.push({path:' '}) <router-view></router-view> 什麼是前端路由?

電商大資料分析平臺nginx配置及flume讀取日誌資訊

一、nginx配置 在本專案中nginx的作用只是接收客戶端傳送的事件,並將相應的session寫入日誌檔案中,所以配置較為簡單,只需要配置寫入的日誌檔案和寫入的格式 1.地址配置 server { listen

s5pv210 -ubootSD卡啟動流程分析

https://blog.csdn.net/wangweijundeqq/article/details/78886155 --------------------- 本文來自 MrT_WANG 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net

深入理解OkHttp3連線Connections

儘管我們只提供給OkHttp一個URL,但OkHttp計劃使用三種類型來連線到伺服器:URL、地址(Address)、和路由(Route)。 URLs URL(比如https://github.com/square/okhttp)是HTTP和網際網路的基礎。除了是web上

docker 基礎教程-入門--簡單製作映象

前言            一般情況下,我們中直接使用docker官網的庫,就可以找到我們日常開發中需要的映象,比如:ubuntu、tomcat、apache、nginx、php、mysql、redi

Spring Boot乾貨系列啟動原理解析

前言       前面幾章我們見識了SpringBoot為我們做的自動配置,確實方便快捷,但是對於新手來說,如果不大懂SpringBoot內部啟動原理,以後難免會吃虧。所以這次博主就跟你們一起一步步揭開SpringBoot的神祕面紗,讓它不在神祕。 正文 我

演算法連結串列

(一)連結串列和陣列都是一種線性結構 陣列是一段連續的儲存空間 連結串列空間不一定保證連續,為臨時分配 (二)連結串列的分類 按連線方向 單鏈表 雙鏈表 按有環無環 普通連結串列 迴圈連結串列 (三)連結串

需求分析說明書

3.需求規定   3.1對功能的規定 a.使用者:指導老師、學生、管理員; b.輸入:指導老師網上上報論文題目、學生網上選題及選指導老師、上傳各類檔案; c.事務處理:確定學生及導師名單、生成開題及答辯分組名單、統計各項成績、提供有關畢業設計的規定和相關知識馮資訊; d.輸出:開題及

阿里伺服器的web專案釋出之路將web專案釋出到伺服器

1.配置阿里雲的安全組,主要是允許8080,80埠的訪問,這樣做的目的主要是為了能讓外網進行訪問,當然,這個地方也能設定專門網段訪問你的公網,配置如下所示 這個地方你也可以通過克隆的方式新增。 8080:被用於WWW代理服務的,可以實現網頁瀏覽,經常在訪問某個網站或使用代理伺服器的

Libcap庫學習抓包流程

理解了Libpcap的工作原理,下面將介紹如何利用Libpcap庫進行資料包的捕獲。其具體的程式設計流程如下: (1)網路裝置查詢 網路裝置查詢的目的就是發現可用的網絡卡,它的實現函式是pcap_lookupdev(),如果當前有多個網絡卡,它會返回一個網路裝置名指標列表。 (2)開