openstack 版本:Newton
注:博文圖片采用了很多大牛博客圖片,僅作為總結學習,非商用。
該圖全面的說明了nova創建虛機的過程,從邏輯的角度清晰的描述了前端請求創建虛擬機之后發生的一系列反應。
上圖是以邏輯的關系說明虛機創建的流程,並沒有涉及到真正的代碼,下面這張圖則是從代碼的角度來看虛機的創建過程。兩張邏輯圖相輔相成,能夠快速對nova創建虛機流程有一個認識。
上一篇博文已經將nova創建虛機的流程分析到restful調用具體的函數。如下圖所示,本篇將從該函數開始分析,展開nova服務的代碼文件。
上圖的create函數是nova api的入口函數,所有nova api的調用都是從該函數開始的。
從該函數開始到nova調用底層驅動創建虛擬機,要經過的調用流程如下:
nova.api.openstack.compute.servers.py::Controller:create ->nova.compute.api.py::API:create ->nova.compute.api.py::API:_create_instance ->nova.comductor.ComputeTaskAPI.py::build_instances ->nova.conductor.rpcapi.py::ComputeTaskAPI:build_instances ->nova.conductor.manager.py::ComputeTaskAPI.py:build_instances ->nova.compute.rpcapi.ComputeManager.py::build_and_run_instance ->nova.compute.manager.py::ComputeManager:_do_build_and_run_instance ->nova.compute.manager.py::ComputeManager:_build_and_run_instance ->driver
nova.api.openstack.compute.servers.py:: Controller:create 指該create函數的所在路徑是nova文件夾下的/nova/api/openstack/compute/servers.py中的create方法
同理:nova.compute.api.py::API:create 指該create方法在/nova/compute/api.py中的create方法。
所以這個調用的順序就是如下圖所示:
那么接下來就詳細分析create()函數方法。
想要搞明白create函數做了什么,就要弄清楚函數傳入的參數是什么。create傳入了三個參數,分別是self,req,body。
其中self是類方法的標識,如果java類中函數的 "this" 字段。那么req、body分別是什么呢?使用python中print打印到文件的方法,輸出了req與body的內容。
req
POST /v2.1/servers HTTP/1.0 Accept: application/json Accept-Encoding: gzip, deflate Connection: keep-alive Content-Length: 323 Content-Type: application/json Host: 192.168.252.134:8774 User-Agent: python-novaclient X-Auth-Project-Id: 836c0b02b549489eac82733267830e60 X-Auth-Token: 31475f46361e41d49c3aa519531192c2 X-Domain-Id: None X-Domain-Name: None X-Identity-Status: Confirmed X-Is-Admin-Project: False X-Project-Domain-Id: default X-Project-Domain-Name: Default X-Project-Id: 836c0b02b549489eac82733267830e60 X-Project-Name: demo X-Role: Member,anotherrole X-Roles: Member,anotherrole X-Service-Catalog: [{"endpoints": [{"adminURL": "http://192.168.252.134:8774/v2.1", "region": "RegionOne", "internalURL": "http://192.168.252.134:8774/v2.1", "publicURL": "http://192.168.252.134:8774/v2.1"}], "type": "compute", "name": "nova"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8774/v2/836c0b02b549489eac82733267830e60", "region": "RegionOne", "internalURL": "http://192.168.252.134:8774/v2/836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8774/v2/836c0b02b549489eac82733267830e60"}], "type": "compute_legacy", "name": "nova_legacy"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8776/v2/836c0b02b549489eac82733267830e60", "region": "RegionOne", "internalURL": "http://192.168.252.134:8776/v2/836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8776/v2/836c0b02b549489eac82733267830e60"}], "type": "volumev2", "name": "cinderv2"}, {"endpoints": [{"adminURL": "http://192.168.252.134:9696/", "region": "RegionOne", "internalURL": "http://192.168.252.134:9696/", "publicURL": "http://192.168.252.134:9696/"}], "type": "network", "name": "neutron"}, {"endpoints": [{"adminURL": "http://192.168.252.134/identity_v2_admin", "region": "RegionOne", "internalURL": "http://192.168.252.134/identity", "publicURL": "http://192.168.252.134/identity"}], "type": "identity", "name": "keystone"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8776/v1/836c0b02b549489eac82733267830e60", "region": "RegionOne", "internalURL": "http://192.168.252.134:8776/v1/836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8776/v1/836c0b02b549489eac82733267830e60"}], "type": "volume", "name": "cinder"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8080", "region": "RegionOne", "internalURL": "http://192.168.252.134:8080/v1/AUTH_836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8080/v1/AUTH_836c0b02b549489eac82733267830e60"}], "type": "object-store", "name": "swift"}, {"endpoints": [{"adminURL": "http://192.168.252.134:8776/v3/836c0b02b549489eac82733267830e60", "region": "RegionOne", "internalURL": "http://192.168.252.134:8776/v3/836c0b02b549489eac82733267830e60", "publicURL": "http://192.168.252.134:8776/v3/836c0b02b549489eac82733267830e60"}], "type": "volumev3", "name": "cinderv3"}, {"endpoints": [{"adminURL": "http://192.168.252.134:9292", "region": "RegionOne", "internalURL": "http://192.168.252.134:9292", "publicURL": "http://192.168.252.134:9292"}], "type": "image", "name": "glance"}] X-Tenant: demo X-Tenant-Id: 836c0b02b549489eac82733267830e60 X-Tenant-Name: demo X-User: demo X-User-Domain-Id: default X-User-Domain-Name: Default X-User-Id: ac86920aec8c443f9fad33283599a17c X-User-Name: demo {"server": {"name": "demo", "imageRef": "ec8f8b10-beb4-4802-9158-7b3ca8357d16", "availability_zone": "nova", "flavorRef": "1", "OS-DCF:diskConfig": "AUTO", "max_count": 1, "min_count": 1, "networks": [{"uuid": "cf8411d0-85b4-4534-9b7c-aed9dbecaafe"}], "security_groups": [{"name": "2a2f7994-a555-45be-9909-3bb06b1f4811"}]}}
req是http報文的全部內容,包括報文頭,報文內容。其中很熟悉的字段:X-Auth-Token是已經獲得的token,還有獲得Token時返回的服務列表Catalog。會不會有人好奇為什么發送的不是賬號和密碼?而是Token?在登陸上openstack dashboard時賬號和密碼都被驗證,后面的操作全都是基於Token來操作的。
報文內容中包含一個server字典,這是我們填寫的創建虛機的數據。可以看到下面的代碼中有在創建虛機時必填的參數,name,鏡像,flavor,network等。
{"server": { "name": "demo", "imageRef": "ec8f8b10-beb4-4802-9158-7b3ca8357d16", "availability_zone": "nova", "flavorRef": "1", "OS-DCF:diskConfig": "AUTO", "max_count": 1, "min_count": 1, "networks": [{"uuid": "cf8411d0-85b4-4534-9b7c-aed9dbecaafe"}], "security_groups": [{"name": "2a2f7994-a555-45be-9909-3bb06b1f4811"}] } }
再來看body中的內容是什么
{
u'server':
{
u'name': u'demo',
u'imageRef': u'ec8f8b10-beb4-4802-9158-7b3ca8357d16',
u'availability_zone': u'nova',
u'flavorRef': u'1',
u'OS-DCF:diskConfig': u'AUTO',
u'max_count': 1,
u'min_count': 1,
u'networks': [{u'uuid': u'cf8411d0-85b4-4534-9b7c-aed9dbecaafe'}],
u'security_groups': [{u'name': u'2a2f7994-a555-45be-9909-3bb06b1f4811'}]
}
}
可以看到body中的內容是req內容的一部分,是post方法的內容。
搞清楚了傳入的數據,下面就是函數處理過程。
這里是該函數最重要的調用。調用了compute/api.py中的create方法去創建虛機。
總結來說,該函數主要做的工作:
/nova/api/openstack/compute/server.py::create()
1 獲取客戶端傳入的虛擬機參數
2 獲取虛擬機名並檢查是否合理
3 檢查API版本
4 構造用戶id,項目id,可用域字典
5 獲取可用域
6 塊設備映射
7 獲取虛機的磁盤鏡像uuid
8 獲取客戶端需求的網絡
9 獲取續集規格ID
10 調用compute_api.create()
11 將虛擬機信息轉化為字典
12 添加訪問當前虛擬機資源的url
主要任務是從傳遞過的req中獲取各種創建虛擬機所需要的參數信息,做簡單必要驗證,然后將獲取的一系列參數(image_uuid,name,insts_type等)
作為nova/compute/api.py中的API類的create()方法參數,最后將返回的信息處理。那么下一節的內容就是要探究調用函數/nova/compute/api.py中的create()函數
完成了什么樣的工作。