nova狀態同步

服務初始化階段

nova-compute服務啓動時調用manager中的host初始化函數數據庫

self.manager.init_host()

在host初始化函數中完成以下操做:api

#初始化libvirt的事件處理
self.driver.init_host(host=self.host)

#註冊生命週期事件的處理函數
self.init_virt_events()

#處理evacuated的虛擬機
經過libvirt接口獲取本節點上全部的虛擬機,再查詢這些虛擬機在數據庫中的host信息。若是host與當前節點不一致,說明是已經撤離的虛擬機,直接destroy。
self._destroy_evacuated_instances(context)

#虛擬機狀態同步
for instance in instances:
    wait_ticks = self._init_instance(context, instance,
    wait_ticks=wait_ticks)

_init_instance完成了虛擬機狀態的同步,同步規則以下:網絡

  1. 若是數據庫中虛擬機已經shutdown,或者處於error狀態,而且任務狀態不是resize_migrating,則不作任何處理。若是任務狀態是resize_migrating的話,後續還要作一些處理。
  2. 若是虛擬機已經處於deleted狀態,可是數據庫中尚未標記爲刪除,則須要更新配額相關的數據,而且刪除數據庫中的記錄。此虛擬機狀態即恢復完畢,開始恢復下一臺。
  3. 若是虛擬機不是上面的狀態,則須要恢復雲主機的網絡設備(當前配置的vif_driver是LibvirtGenericVIFDriver,tap設備由libvirt生成管理,這裏就直接跳過了)
  4. 若是虛擬機的task狀態爲resize_migrating,說明在遷移過程當中服務關閉了,保險起見須要恢復虛擬機狀態finish_revert_migration
  5. 以上操做完成以後,若是數據庫中記錄的狀態是running可是節點上虛擬機狀態不爲running,經過resume_state_on_host_boot啓動虛擬機(其實是hard_reboot操做,可是不更新數據庫狀態)。

 

init_host中對事件處理的初始化:app

#註冊異常處理函數,這裏的libvirt_error_handler是空的,也就是異常不作處理
libvirt.registerErrorHandler(libvirt_error_handler, None)
#向libvirt註冊一個事件
libvirt.virEventRegisterDefaultImpl()
#
self._init_events()

_init_events中:dom

#建立一個隊列,用於存儲事件消息
#建立一對管道,用於事件消息的通知
self._init_events_pipe()
#啓動一個系統原生線程,線程內用循環監聽上面註冊的libvirt事件。
_native_thread
        libvirt.virEventRunDefaultImpl()
#啓動一個綠色線程,線程內用一個循環分發監聽到的libvirt事件。
eventlet.spawn(self._dispatch_thread)

事件分發流程_dispatch_thread函數

#讀取上面創建的管道內容,若是讀出數據,說明隊列中有消息待處理。沒有消息則退出這次循環。
_c = self._event_notify_recv.read(1)
#嘗試讀取事件隊列
event = self._event_queue.get(block=False)
#若是是生命週期事件,則進入生命週期事件處理函數
self.emit_event(event)
#處理鏈接斷開事件(告警日誌打印,重置nova與libvirt的鏈接conn)
conn = last_close_event['conn']

生命週期事件處理函數emit_event(self, event)ui

#調用註冊的事件處理函數
self._compute_event_callback(event)

註冊事件處理函數init_virt_eventsspa

#此處註冊了handle_events做爲生命週期事件的處理函數
self.driver.register_event_listener(self.handle_events)

handle_events-->>handle_lifecycle_event線程

#按照以下的關係同步虛擬機在openstack層的電源狀態
#EVENT_LIFECYCLE_STOPPED -> SHUTDOWN
#EVENT_LIFECYCLE_STARTED -> RUNNING
#EVENT_LIFECYCLE_PAUSED -> PAUSED
#EVENT_LIFECYCLE_RESUMED -> RUNNING

self._sync_instance_power_state(context,
                                instance,
                                vm_power_state)

_sync_instance_power_state日誌

#若是虛擬機的宿主機不是當前節點,說明虛擬機作了遷移,這種虛擬機直接跳過,不作同步。
if self.host != db_instance.host

#虛擬機的任務狀態不爲空,說明當前事件只是一個任務的中間狀態,也直接跳過不作處理
elif db_instance.task_state is not None

#事件上報的虛擬機電源狀態與數據庫電源狀態不一致的狀況下,更新數據庫中的虛擬機電源狀態。
if vm_power_state != db_power_state:
    db_instance.power_state = vm_power_state
    db_instance.save()
#數據庫中的虛擬機狀態爲ACTIVE
#接收到SHUTDOWN/CRASHED -> call stop api
#接收到SUSPENDED -> call stop api
#接收到PAUSED -> 虛擬機異常pause,ignore
#接收到NOSTATE -> 虛擬機丟失,忽略
#數據庫中的虛擬機狀態爲STOPPED,而上報的生命週期事件不是NOSTATE/SHUTDOWN/CRASHED其中之一,則強制關閉虛擬機。
self.compute_api.force_stop(context, db_instance)
#數據庫中的虛擬機狀態爲PAUSED,上報的生命週期事件爲SHUTDOWN/CRASHED,則認爲一個暫停狀態的虛擬機被關機了,強制關閉虛擬機。
self.compute_api.force_stop(context, db_instance)
#數據庫中虛擬機狀態爲SOFT_DELETED或者DELETED,而上報的事件不是NOSTATE或者SHUTDOWN,則發出日誌告警。

nova-compute服務啓動時,libvirt driver會同步加載,並與libvirt創建一個長鏈接。經過這個鏈接註冊了libvirt的生命週期事件的回調函數

#註冊生命週期事件,只有這些事件發生時,後面virEventRunDefaultImpl纔會被觸發。
wrapped_conn.domainEventRegisterAny(
        None,
        libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
        self._event_lifecycle_callback,
        self)

當libvirt監聽到事件發生時,會調用註冊的回調函數

#將事件添加到隊列中
self._queue_event(virtevent.LifecycleEvent(uuid, transition))

_queue_event

#加入隊列
self._event_queue.put(event)
#經過管道通知給dispatch綠色線程
c = ' '.encode()
self._event_notify_send.write(c)
self._event_notify_send.flush()

定時任務同步

nova-compute在服務啓動的最後階段啓動了一個定時任務_sync_power_states。這個定時任務的主要功能是同步節點上的虛擬機電源狀態與數據庫記錄保持一致。最終也是經過與事件同步同樣的_sync_instance_power_state同步電源狀態。

總結

nova中的狀態同步有如下幾種狀況:

1.服務啓動時

  • 節點上執行了evacuate操做的虛擬機直接destroy刪除。
數據庫狀態 節點狀態 任務狀態 處理
SOFT_DELETED - 非RESIZE_MIGRATING -
ERROR - 非RESIZE_MIGRATING -
DELETED - - 清理資源
- - RESIZE_MIGRATING 回滾遷移操做
RUNNING 非RUNNING - 啓動

2.事件通知及定時任務的狀態同步

數據庫狀態 上報狀態 處理
ACTIVE SHUTDOWN stop
ACTIVE CRASHED stop
ACTIVE SUSPENDED stop
ACTIVE PAUSED ignore
ACTIVE NOSTATE ignore
STOPPED 非NOSTATE/SHUTDOWN/CRASHED destroy
PAUSED SHUTDOWN/CRASHED destroy
SOFT_DELETED 非NOSTATE/SHUTDOWN 日誌告警
DELETED 非NOSTATE/SHUTDOWN 日誌告警

 

本文來自網易雲社區,經做者嶽文遠受權發佈。

原文地址:nova狀態同步

更多網易研發、產品、運營經驗分享請訪問網易雲社區。 

相關文章
相關標籤/搜索