nova状态同步
服务初始化阶段
nova-compute服务启动时调用manager中的host初始化函数
self.manager.init_host()
在host初始化函数中完成如下操作:
#初始化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完成了虚拟机状态的同步,同步规则如下:
- 如果数据库中虚拟机已经shutdown,或者处于error状态,并且任务状态不是resize_migrating,则不做任何处理。如果任务状态是resize_migrating的话,后续还要做一些处理。
- 如果虚拟机已经处于deleted状态,但是数据库中还没有标记为删除,则需要更新配额相关的数据,并且删除数据库中的记录。此虚拟机状态即恢复完毕,开始恢复下一台。
- 如果虚拟机不是上面的状态,则需要恢复云主机的网络设备(当前配置的vif_driver是LibvirtGenericVIFDriver,tap设备由libvirt生成管理,这里就直接跳过了)
- 如果虚拟机的task状态为resize_migrating,说明在迁移过程中服务关闭了,保险起见需要恢复虚拟机状态
finish_revert_migration - 以上操作完成之后,如果数据库中记录的状态是running但是节点上虚拟机状态不为running,通过
resume_state_on_host_boot启动虚拟机(实际上是hard_reboot操作,但是不更新数据库状态)。
init_host中对事件处理的初始化:
#注册异常处理函数,这里的libvirt_error_handler是空的,也就是异常不做处理
libvirt.registerErrorHandler(libvirt_error_handler, None)
#向libvirt注册一个事件
libvirt.virEventRegisterDefaultImpl()
#
self._init_events()
_init_events中:
#创建一个队列,用于存储事件消息
#创建一对管道,用于事件消息的通知
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)
#调用注册的事件处理函数
self._compute_event_callback(event)
注册事件处理函数init_virt_events
#此处注册了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状态同步
更多网易研发、产品、运营经验分享请访问网易云社区。
nova状态同步的更多相关文章
- Postman+Postman interceptor的安装和使用-解决把chrome浏览器登录状态同步到postman进行有依赖的接口测试 Postman 使用方法详解
Postman+Postman interceptor的安装和使用-解决把chrome浏览器登录状态同步到postman进行有依赖的接口测试 问题引入:做接口测试时,有依赖关系的接口往往不好测试( ...
- 图解kubernetes容器状态同步机制核心实现
在K8s中将Pod调度到某一台Node节点之后,后续的状态维护信息则是由对应机器上的kubelet进行维护,如何实时反馈本地运行状态,并通知apiserver则是设计的难点, 本节主要是通过感知Pod ...
- vue父子组件状态同步的最佳方式
哈喽!大家好!我是木瓜太香,一位老牌儿前端工程师,平时我们在使用 vue 开发的时候,可能会遇到需要父组件与子组件某个状态需要同步的情况,通常这个是因为我们封装组件的时候有一个相同的状态外面要用,里面 ...
- vue父子组件状态同步的最佳方式续章(v-model篇)
大家好!我是木瓜太香!一名前端工程师,之前写过一篇<vue父子组件状态同步的最佳方式>,这篇文章描述了大多数情况下的父子组件同步的最佳方式,也是被开源中国官方推荐了,在这里表示感谢! 这次 ...
- zookeeper有几种部署模式? zookeeper 怎么保证主从节点的状态同步?
一.zookeeper的三种部署模式 Zookeeper 有三种部署模式分别是单机模式.伪集群模式.集群模式.这三种模式在不同的场景下使用: 单机部署:一般用来检验 Zookeeper 基础功能,熟悉 ...
- Android系统移植与调试之------->增加一个双击物理按键打开和关闭闪光灯并将闪光灯状态同步到下拉菜单中
最近有一个客户有这样的需求: 1.在[设置]--->[无障碍]中添加一个开关按钮. 如果打开开关的话,双击某个物理按键的时候,打开闪光灯,再双击该物理按键的时候,关闭闪光灯. 如果关闭开关的话, ...
- java线程控制、状态同步、volatile、Thread.interupt以及ConcurrentLinkedQueue
在有些严格的系统中,我们需要做到干净的停止线程并清理相关状态.涉及到这个主题会带出很多的相关点,简单的总结如下: 我们知道,在java中,有一个volatile关键字,其官方说明(https://do ...
- java多线程之hashmap concurrenthashmap的状态同步
最近在高并发的系统中发现,concurrenthashmap除了大家熟知的避免循环期间发生ConcurrentModificationException异常外,还有重要的一点是Retrievals r ...
- 浅谈js拖拽
本文来自网易云社区 作者:刘凌阳 前言 本文依据半年前本人的分享<浅谈js拖拽>撰写,算是一篇迟到的文章. 基本思路 虽然现在关于拖拽的组件库到处都是,HTML5也把拖放纳入了标准.但考虑 ...
随机推荐
- 蓝魔i7s刷机
,电脑管家,豌豆荚之类的PC工具 5. 安装MFT6.0.43.exe, 注意:MFT6.0.43需要对应的ISOC和USB驱动,不可使用其它版本 6. 将CUSTOM_CONFIG..INI文件复制 ...
- PHP正则自动验证传入数据
本文出至:新太潮流网络博客 /** * [is_string_regular_type 正则自动验证传入数据] * @E-mial wuliqiang_aa@163.com * @TIME 2017- ...
- [luogu P4230]连环病原体
[luogu P4230] 连环病原体 题意 给定一个长度为 \(n\) 的边序列, 当这个序列的一个子区间内的边都加入图中时产生了环则称其为"加强区间", 求序列中的每条边在多少 ...
- 12.SolrCloud原理
转载自http://blog.csdn.net/u011026968/article/details/50336709 内容涉及:SolrCloud的基础知识.架构.索引创建和更新.查询.故障恢复.负 ...
- 在react中使用intro.js的的一些经验
react逐渐热了起来,但是新的东西毕竟前辈的经验少一些,前段时间自己在react中用到intro.js时,得到的资料甚少,摸索后便将一些心得记录下来了~ 1 intro.js的引入,这一点请看上一篇 ...
- stl vector、红黑树、set、multiset、map、multimap、迭代器失效、哈希表(hash_table)、hashset、hashmap、unordered_map、list
stl:即标准模板库,该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法 六大组件: 容器.迭代器.算法.仿函数.空间配置器.迭代适配器 迭代器:迭代器(iterator)是一种抽象的设计 ...
- <数据结构与算法分析>读书笔记--利用Java5泛型实现泛型构件
一.简单的泛型类和接口 当指定一个泛型类时,类的声明则包括一个或多个类型参数,这些参数被放入在类名后面的一对尖括号内. 示例一: package cn.generic.example; public ...
- leetcode242—Valid Anagram
Given two strings s and t , write a function to determine if t is an anagram of s. Example 1: Input: ...
- 纯css实现弹窗左右垂直居中效果
1.HTML <div class="container"> <div class="dialog"> <div class=&q ...
- C++之内联函数
C++语言新增关键字 inline,用于将一个函数声明为内联函数.在程序编译时,编译器会将内联函数调用处用函数体替换,这一点类似于C语言中的宏扩展. 采用内联函数可以有效避免函数调用的开销,程序执行效 ...