每个虚机都有 vm_states, task_states, power_states 三类状态。 三类状态的使用是复杂的。有些状态容易混淆,有些容易歧义。
也缺少扩展和增加新状态的指南。 本文旨在将其简化解释并精确定义他们的含义,和说明为什么需要他们。还讨论了一种新的用户友好的删除虚机的方法。
-
power_state(供电状态) 是hyphervisor的状态,由compute
worker,自下而上的引入
-
Vm_state(虚机状态)
反映基于API 调用的稳定状态,匹配用户的期望,在API的实现中,为自上而下传递。
-
Task_state (任务状态) 反映在进行中的API 调用的过渡状态。
-
“硬”删除虚机,只要DB是可用,应该总是成功的。
-
供电状态和虚机状态可能互相矛盾,需要单独根据每种情况进行协调处理。
power_state 供电状态
供电状态就是我们针对特定虚机调用 virt 驱动获得的状态。 实际的状态在hypervisor中是有效的反映,在数据库中的供电状态,可以认为是过去一段时间到当前的状态快照。它可以周期性的更新,如果任务对供电状态有影响,在任务结束时会被更新。
总是自下而上,由compute worker报告,覆盖DB中的字段。更新可以针对虚机状态触发协调过程,看下面。
紧跟现有的从libvirt推演来的约定
废弃的状态,BLOCKED, 本质上是RUNNING;SHUTOFF,实际是映射到SHUTDOWN, FAILED,映射到NOSTATE。
vm_state 虚机状态
虚机状态应该描述虚机的当前稳定状态。即是,当前没有进行中的compute API调用状态,虚机状态应该反映,客户期望的虚机实际情况。一个正确虚机状态的例子,ACTIVE,含义为虚机在正常的运行。 一个错误的虚机状态,
SUSPENDING, 它是一个过渡状态,含义为虚机在挂起的过程中,即将变成挂起。
一个过渡状态属于任务状态。
虚机状态应该在任务结束时更新,当任务成功结束时,设置任务状态为None. 没有API 调用, 虚机状态应不被改变。如果任务失败,但是被正确清除(例如,在线迁移失败,但是虚机在源节点上回滚后工作正常),虚机状态应该没有改变。如果任务失败,且无法正常回滚,虚机状态会设为ERROR。
没有一对一的映射的情况。 他们表达的是稍微有点不同的信息。 你不能从一种状态推断另一种,而是两种都需要。例如,当你救援一台虚机,这台虚机用救援镜像运行。这时供电状态可以是RUNNING或BLOCKED。但是虚机状态应该是RESCUED。单独基于供电状态,你无法说出是ACTIVE或RESCUED。
首先,如果有进行中的任务,虚机状态和供电状态可以并可能矛盾。这是由于虚机状态只代表稳定状态。 在任务执行期间,状态在过渡中并不会及时更新。
当没有任务进行时,供电状态和虚机状态应该一致,除非有报错和失败发生。在这些情况下,按单个情况进行处理。
-
如果供电状态=SHUTOFF,但虚机状态=ACTIVE,这很有可能是由于shutdown 命令在虚机中发出。所以供电状态是准确的。这种情况基本等同于一个隐含的stop()
API 调用。虚机状态应该修改为STOPPED。
-
如果供电状态=BLOCKED, 虚机状态=HARD_DELETED,这意味着,用户已经请求删除虚机,但是不知怎么,调用失败了。我们应该重试delete。
-
如果供电状态=BLOCKED, 但是虚机状态=PAUSED, 这个含义可能是在进行virt driver 的pause() 调用前,发个无法预知的问题。在这种情况下,什么是用户最友好的行为? 设为错误?
(现在,_sync_power_states 没有考虑当前的任务,可能会导致奇怪的行为)
Ec2状态同时包含稳定和过渡状态。你需要根据任务状态和虚机状态推断出EC2状态。
清除后的虚机状态。
-
VM在数据库中被创建,但尚未部署。
-
VM用特定的镜像运行。
-
VM使用救急镜像运行。
-
VM用特定镜像暂停。
-
VM用特定镜像挂起,包含有效的内存快照。
-
VM没有运行,镜像在磁盘上。
-
VM不会在计算节点上运行,但磁盘镜像尚留存,可以恢复。
-
从配额和计费角度,VM不存在。VM最终在计算节点上被清除,包括磁盘镜像在内。
-
VM在源节点上停止,但在目标节点上运行。 VM镜像在两个地点存在。(源和目的,不同大小)。系统期望用户确认VM规格调整或恢复调整前状态
-
一些无法恢复的错误发生。只有delete允许被调用到该虚机。
废弃的状态: REBUILDING,MIGRATING,RESIZING,应为任务状态集中的状态。
SHUTOFF也应该去除。这个状态很令人混淆,应该根据shutdown_terminate 标识匹配到STOPPED或DELETED。
task_state 任务状态
任务状态应该代表过渡状态,并是精确地和一个compute API关联,表示针对当前虚机正在操作的任务。任务状态不必用来决定是否虚机状态机允许一个任务。 事实是,任务的进程才是需要的。
删除虚机应该始终允许,并始终成功。用户应该可以从配额中释放更多资源,且不再计费。不幸的是,可能的一种情况,前面的任务吊死了,所以任务状态永远无返回到None,或者virt driver 销毁虚机吊死,或计算节点不可用了,由于网络或硬件问题。所以,我们不应该等待
直到force_delete() 任务能和compute worker通讯并更新虚机状态为 HARD_DELETE。 而应该,不通过compute worker,直接立即虚机状态。换一种说法,force_delete() 任务是纯的数据库操作。实际的清除任务会立即跟进,但供电状态和虚机状态之间的协调是相同的,也会按周期进行触发。
当针对虚机,只有一个任务在运行时,任务状态会被设置。为更新操作的原子性,在任务开始时,必须产生一个唯一任务ID和虚机的ID关联。如果虚机已经有一个任务ID,这意味着另一个任务正在进行中。在任务执行期间,任务ID通过RequestContext数据结构,传递到workers。 在任务中更新任务状态(例如,报告任务进程),任务必须确认虚机的任务ID和当前的任务ID匹配。否则,当前运行的任务被另外一个更高优先级任务占先(目前只有force_delete 任务)。当一个任务结束,任务状态被置为None,
任务ID也被设为None.
另外,由于只有Hard delete能优先于其他任务先执行, 我们现在可能没有必要增加任务ID。但是我们需要在配置任务ID前,先检查虚机状态去看看它不是HARD DELETED。
技术上讲,虚机状态(稳定态)和任务状态(过渡态)是脱节的,你可以将他们组合在一起。
分离的最大好处是,状态过渡的示意图会简单许多。你只要考虑稳定虚机态之间的DFA( deterministic finite automaton (DFA))。 空间小多了。如果某一扩展需要一个新的任务状态,状态的过渡示意图保持不变
在调用compute API 方法的动词的地方,动词的正在进行时更适合用于描述任务状态。 在任务执行期间,任务状态应该永不改变。为了简化状态机,将使用一个分离的字段表达任务的进程
-
None
-
BUILDING
-
IMAGE_SNAPSHOTTING
-
IMAGE_BACKINGUP
-
UPDATING_PASSWORD
-
PAUSING
-
UNPAUSING
-
SUSPENDING
-
RESUMING
-
DELETING
-
STOPPING
-
STARTING
-
RESCUING
-
UNRESCUING
-
REBOOTING
-
REBUILDING
-
POWERING_ON
-
POWERING_OFF
-
RESIZING
-
RESIZE_REVERTING
-
RESIZE_CONFIRMING
-
SCHEDULING
-
BLOCK_DEVICE_MAPPING
-
NETWORKING
-
SPAWNING
-
RESIZE_PREP
-
RESIZE_MIGRATING
-
RESIZE_MIGRATED
-
RESIZE_FINISH
RESIZE_VERIFY 不是过渡状态,而是稳定状态。它是新的规格调整后的虚机状态。
原文:
阅读(2236) | 评论(0) | 转发(0) |