Nova uses the Libvirt event to update the power state of the VM's DB
Https://wiki.openstack.org/wiki/ComputeDriverEvents
Nova Compute manager reports the status of VMS on hypervisor every 10 minutes, allowing Nova to detect the true state of the VM, such as the VM being shutdown by the guest OS or killed by hyper.
_sync_power_states, virtual machine state Refresh, spacing=600
Get the virtual machines on this computer in DB, (call driver's Get_num_instances method to get the number of virtual machines), and cycle through the virtual machines in DB:
A) Ignore virtual machines that have task_state (being processed)
b) Call driver's Get_info method to obtain the node virtual machine information, if not found, power_state=nostate
c) If the power_state in DB is inconsistent with the power_state returned by driver, update the DB with driver
D) If the vm_state=building| in db rescued| resized| suspended| paused| ERROR, ignoring
e) If the vm_state==active in db, and Power_state is [SHUTDOWN, CRASHED, SUSPENDED], call the Nova-api stop interface to halt the virtual machine; if Power_state is [PAUSED | Nostate], ignoring
f) If vm_state==stopped in db, while Power_state is not [Nostate, SHUTDOWN, CRASHED], call Nova-api Stop interface stops the virtual machine
But this will aggravate the hypervisor and have a delay.
Libvirt has domain Events "capability can detect the status of VMS in a timely manner.
RFC discussion:
Http://lists.openstack.org/pipermail/openstack-dev/2013-January/004501.html
Implementation in Libvirt:
- Libvirt.vireventregisterdefaultimpl () registers the default event loop implementation for Libvirt, which uses the default implementation
- Libvirt.vireventrundefaultimpl () iterates through loops and needs to be placed in a "while True" loop to handle events in the Libvirt event loop.
- Conn.domaineventregisterany () Register for event callbacks on Libvirt connection
Implemented in Nova as:
Https://blueprints.launchpad.net/nova/+spec/compute-driver-events
- def queue_event (queue) – Put events in Libvirt into the queue for subsequent dispatch to compute Manager. It runs on a native thread.
- def emit_event (event)-this would dispatch a single event to the compute manager callback. This is the only to being invoked from a greenthread.
- def emit_queued_events ()-This would dispatch all events previously queued via the Queue_event () method. This is the only to being invoked from a greenthread.
- Def Register_event_listener (callback)-register a callback function to receive events. The callback is invoked with a single Parameter-the event object
The actual data associated with events would be provided via a number of classes
- Event-the (abstract) base class for all events. Simply maintains a timestamp indicating when the event was raised
- Instanceevent-the (abstract) base class for all events associated with an individual instance. Maintains an instance UUID.
- Lifecycleevent-the class used for reporting changes in a instance state (started/stopped/paused/resumed)
Implementation Details:
https://review.openstack.org/#/c/21802/
Handle lifecycle events in the Compute Manager
In time processing, if the status of the event is currently received as in DB, the State in the DB is not updated in time.
Self._sync_instance_power_state to update, (why not update the DB directly?) )
Https://review.openstack.org/#/q/topic:bp/compute-driver-events,n,z
Get the Libvirt event into a pipe and handle the events in the pipe in Compute Manager.
https://review.openstack.org/#/c/21801/5/nova/virt/libvirt/driver.py
Nova Libvirt Event