OpenStack建立一個虛擬機,涉及到三種狀態,vm_state,task_state和power_state。html
先總結幾點:數據庫
Power_state是咱們調用虛擬機中驅動得到的一個狀態,事實上hypervisor的狀態纔是權威的。數據庫中power_state只是以前狀態的一個快照,網絡
會被週期性更新,而且在有任務改變了power_state後要更新數據庫。ui
一、怎樣更新?htm
一般是」自下而上「,由計算節點產生,重寫數據庫。這個更新過程可能引發和vm_state的一致性衝突,以下。blog
二、power_state命名慣例進程
取決於ibvirt返回的狀態。內存
廢棄的狀態:資源
BLOCKED,本質上應該是RUNNING;同步
SHUTOFF,如今是SHUTDOWN;
FAILED,如今是NOSTATE。
vm_sate描述虛擬機當前穩定狀態,而非過渡狀態。若是沒有running_tasks,虛擬機就應該是用戶期待的狀態,好比active。ACTIVE是一個vm_state,由於它表明虛擬機正常運行;而SUSPENDING是一個過渡狀態,表明n秒後虛擬機將被掛起,因此應該屬於task_state。
一、vm_stae怎樣更新
vm_state僅在任務結束後更新,即當一個任務成功結束而且設置task_state狀態爲None。
當有API調用時,vm_state永遠不能改變。若是任務失敗,而且合適的清理後(好比live遷移失敗,任務回滾,虛擬機在源節點正常運行),虛擬機狀態不變。若是任務失敗而且不能回滾,vm_state狀態被置爲ERROR。
二、vm_state命名慣例:使用一個形容詞
三、vm_state和power_state關係?
兩者不是一一映射,表明的側重點不一樣,不能經過推理從一個獲得另外一個,因此都是須要的。
好比,當你去修復一個虛擬機,虛擬機從一個rescue鏡像啓動,此時power_state狀態爲RUNNING,可是vm_state狀態只能是RESCUED。單單靠power_state是不能肯定vm_state是ACTIVE仍是RESCUED。
四、power_state和vm_state狀態不一致,如何修正?
首先,有正在運行的任務時,vm_state和power_state極有可能不一樣,由於vm_state表明一個穩定狀態,在任務運行期間,狀態是過分狀態,vm_state原本就是過時的。
當沒有任務運行時,power_state和vm_state應該保持一致,除非出錯或者失敗,這種狀況,要具體分析。
a、若是power_state=SHUTOFF,可是vm_state=ACTIVE,極有多是虛擬機內部shotdown命令出錯,因此power_state正確。一個粗暴但等價的方法,手動調用一個內部方法stop()API,虛擬機應該被修正爲STOPPED。
b、若是power_state=BLOCKED,vm_state=HARD_DELETED,表明用戶已經要求刪除虛擬機可是過程失敗了。因此嘗試再次刪除。
c、若是power_state=BLOCKED,vm_state=PAUSED,表明多是pause()方法調用前出了不可預料的問題。此時修正方法就看怎樣對用戶最友好了,maybe設置vm_state爲ERROR。
到此,會發現 _sync_power_states (同步電源狀態)不鳥正在執行的任務,可能致使奇怪的錯誤。
五、如何從vm_state中得到和EC2等價的狀態?
ec2狀態包含穩定狀態和過渡狀態。因此須要同時根據task_state和vm_state來推斷ec2狀態。
vm_state以下:
vm_state中廢棄的狀態REBUILDING,MIGRATING,RESIZING都放在了task_state中。而SHUTOFF不用了,由於這個狀態很費解,應該根據shutdown_terminate標記被劃分到STOPPED或者DELETED。
task_state表明過渡狀態,和一個computeAPI緊密相關,代表虛擬機當前執行哪一個任務。處於vm_state的虛擬機是不會有task_state,只有正在運行的進程有task_state。
一、特定任務:force_delete(或者hard delete)
虛擬機何時都能成功刪除。用戶刪除虛擬機能夠釋放配額裏更多資源,再也不被收費。不幸的是,可能出現這種狀況,一個前置任務卡住了因此task_state永遠不能到None,或者虛擬驅動在銷燬虛擬機時卡住了,再或者計算節點由於網絡/硬件的緣由不可用而沒法執行銷燬虛擬機操做。因此,不該該等到force_delete() 任務得到計算節點而後更新虛擬機狀態爲HARD_DELETED。而應該是說,vm_state立馬更新而不去檢查計算節點。換句話說,force_delete() 任務是一個純粹的數據庫操做。一些善後工做(真正的清除工做)隨後進行,也不須要power_state和vm_state之間的一致性操做,由於它們會被按期觸發。
二、如何更新?
task_state被設置當確認它是虛擬機上惟一執行的任務時。要作到原子更新,任務開始會生成一個獨一無二的task_id(uuid格式)和虛擬機id關聯。若是虛擬機已經有一個VM id,說明已經有別的任務在運行。在任務執行過程當中,task_id經過RequestContext數據格式傳播。在任務執行中途若是要更新ask_state,必須確認虛擬機的task_id匹配當前執行任務的id,不然新任務搶佔當前任務(目前只有force_delete)。當任務成,task_state置爲None,同時task_id置爲None。
由於hard delete是惟一一個能夠搶佔其餘任務的任務,咱們不必當即設置task_id,可是須要檢查vm_state以確認它不是HARD_DELETE而不是去檢查task_id是否匹配。
三、真的要分開vm_state和task_state嗎?
從技術上講,虛擬機狀態(穩定)和任務狀態(過渡)沒有交集,能夠組合使用。分開最大的好處就是狀態轉換圖簡單得多——只要考慮vm_state之間的DFA。若是須要增長一個新task_state,狀態轉換圖保持不變。
四、命名變化
最好用動詞+」ing「來描述task_state,且這個動詞是compute API方法。任務執行期間,task_state不變。要表述任務的進展,應該使用一個單獨的領域,而不是簡化狀態機。
廢棄的狀態:
RESIZE_VERIFY不是一個過渡狀態,而是穩定狀態。變成了vm_state中的新狀態RESIZED。
參考:
https://wiki.openstack.org/wiki/VMState
http://docs.openstack.org/developer/nova/devref/vmstates.html#preconditions-for-commands