Implement force_detach for safe cleanup¶
包含您的 Launchpad 蓝图的 URL
https://blueprints.launchpad.net/cinder/+spec/implement-force-detach-for-safe-cleanup
目前,当卷处于卡住的“正在连接”或“正在断开”状态时,Cinder数据库和后端存储的状态同步没有API。例如,如果卷卡在断开状态,但存储驱动程序已连接/导出该卷,管理员可以使用‘cinder reset-state <vol_id>’将卷的状态设置为‘已断开’。这将与后端存储状态不匹配,后端存储仍然将卷连接/导出到计算主机和nova实例。如果卷状态重置为‘可用’和‘已断开’,则可以将其附加到第二个实例(注意这并非多重附加),并导致数据损坏。本规范建议添加Cinder API,允许管理员以安全的方式将状态设置为‘可用’和‘已断开’,这意味着后端存储和Cinder数据库是同步的。曾尝试合并一个Nova规范来添加一个‘--force’选项,但它已经停滞,并且可能会被一些Nova代码更改所取代。请参阅:https://review.openstack.org/#/c/84048/44 Nova开发者提出了一种幂等的‘nova volume-detach…’,它将 1) 从VM断开卷(libvirt.detach) 2) 调用Cinder进行断开并忽略Cinder错误 3) 从Nova DB中删除BlockDeviceMapping。这将清理Nova端,但可能使Cinder处于错误/不同步状态,并需要手动清理Cinder,即 cinderclient ‘force-detach’。(cinderclient补丁:https://review.openstack.org/#/c/187305/)
问题描述¶
卷卡在阻止用户使用该卷或更改状态的状态(例如‘正在连接’、‘正在删除’、‘正在创建’、‘正在断开’)的情况并不少见。python-cinderclient具有‘reset-state’命令,允许管理员将Cinder数据库中的卷状态更改为任何所需的状态。然而,为了以安全可靠的方式解决问题,管理员必须检查卷相对于后端存储和Nova的状态。根据后端存储的元数据,卷是否已连接?计算主机是否有iSCSI连接(或FC)?Nova BlockDeviceMapping是否有该卷的条目?清理Cinder DB是可能的,清理存储后端也是可能的,更改Nova DB需要直接更改(SQL命令)Nova数据库。同步状态需要详细了解所有组件,并且通常需要对生产系统进行侵入性和危险的更改。更改python-cinderclient ‘reset-state’已被提出[1],但该想法被拒绝,转而支持实现单独的API以实现所需的状态[2]。本规范旨在实现‘force_detach’。已经存在一个‘force_delete’ API来帮助处理卡在‘正在创建’或‘正在删除’状态的卷。事实上,已经存在一个force_detach API,它调用terminate_connection和detach,但似乎在代码库的其他地方未被使用,应该正确实现以测试驱动程序是否可以遵守,并且在驱动程序成功的情况下,该函数应该清理Cinder DB。可以认为应该有一个类似的‘force_attach’或更恰当地命名为‘force_rollforward_attach’,但仅仅强制断开卷似乎可以将卷恢复到可以再次尝试连接的状态。
用例¶
用例1:Cinder DB ‘正在连接’,存储后端‘可用’,Nova DB不显示该卷的块设备。尝试使用‘nova volume-attach <instance> <volume_id>’附加卷。Cinder DB设置为‘正在连接’,但卷从未连接。当前修复:使用python-cinderclient ‘reset-state’将Cinder DB设置为‘可用’将解决此问题。建议修复:尝试从Nova断开连接将失败,因为Nova不知道此卷。实现Cinder force_detach并将其暴露给cinderclient将允许cinder调用后端进行清理(默认实现是terminate_connection和detach,但可以被覆盖),然后将Cinder DB状态设置为‘可用’和‘已断开’。
用例2:Cinder DB ‘正在连接’,存储后端‘已连接’,Nova DB显示该卷的块设备。Cinder DB设置为‘正在连接’,但卷已连接。当前修复:使用python-cinderclient ‘reset-state’将Cinder DB设置为‘可用’将导致不同步状态,因为卷实际上已连接。Nova将不允许重新连接此卷。建议修复:尝试从Nova断开连接将在Nova端清理(在Nova更改之后),但在Cinder中失败,因为状态是‘正在连接’。实现Cinder force_detach并将其暴露给cinderclient将允许cinder调用后端进行清理(默认实现是terminate_connection和detach,但可以被覆盖),然后将Cinder DB状态设置为‘可用’和‘已断开’。
用例3:Cinder DB ‘正在断开’,存储后端‘可用’,Nova DB不显示该卷的块设备。尝试使用‘nova volume-detach <instance> <volume_id>’断开卷。Cinder DB设置为‘正在断开’,并且卷实际上已断开。当前修复:使用python-cinderclient ‘reset-state’将Cinder DB设置为‘可用’将解决此问题。建议修复:尝试从Nova断开连接将失败,因为Nova不知道此卷。实现Cinder force_detach并将其暴露给cinderclient将允许cinder调用后端进行清理(默认实现是terminate_connection和detach,但可以被覆盖),然后将Cinder DB状态设置为‘可用’和‘已断开’。
用例4:Cinder DB ‘正在断开’,存储后端‘已连接’,Nova DB具有该卷的块设备。尝试使用‘nova volume-detach <instance> <volume_id>’断开卷。Cinder DB设置为‘正在断开’,但卷实际上已连接。当前修复:使用python-cinderclient ‘reset-state’将Cinder DB设置为‘可用’将导致不同步状态,因为卷实际上已连接。Nova将不允许重新连接此卷。建议修复:尝试从Nova断开连接将在Nova端清理(在Nova更改之后),但在Cinder中失败,因为状态是‘正在连接’。实现Cinder force_detach并将其暴露给cinderclient将允许cinder调用后端进行清理(默认实现是terminate_connection和detach,但可以被覆盖),然后将Cinder DB状态设置为‘可用’和‘已断开’。
用例5:在连接期间,initialize_connection()超时。Cinder DB为‘可用’,卷已连接,Nova DB不显示块设备。当前修复:无法通过reset-state修复。需要对后端存储进行手动干预。建议修复:nova/volume/cinder.py L#366中的代码调用initialize_connection,可能会超时。正在审查一个补丁,将其放入try块中,并在出现异常时进行清理:https://review.openstack.org/#/c/138664/6/nova/volume/cinder.py 可以修改此补丁以调用force_detach()而不是terminate_connection,以确保将DB状态条目设置为可用,并允许驱动程序断开连接和调用任何驱动程序特定的代码进行清理。
提议的变更¶
Nova必须更改,因为它当前检查Cinder DB中的状态,如果Cinder未显示卷为‘已连接’和‘正在使用’,则会使‘volume-detach’调用失败。建议Nova忽略Cinder状态并执行libvirt.detach和从BDM中删除卷条目。Nova将调用Cinder并忽略任何错误,将清理留在Cinder端通过手动干预完成(即‘cinder force-detach….’(将提供Nova更改的链接,尽快)
Cinder force-detach API当前调用
volume_api.terminate_connection(...)
self.volume_api.detach(...)
这将修改为调用VolumeManager,并使用新的force_detach(…)
api/contrib/volume_actions.py: force_detach(…)
try:
volume_rpcapi.force_detach(...)
except: #catch and add debug message
raise #something
self._reset_status(..) #fix DB if backend cleanup is successful
volume/manager.py: force_detach(…)
self.driver.force_detach(..)
各个驱动程序将根据需要实现force_detach,很可能调用terminate_connection(..)和其他清理。force_detach(..) api应该是幂等的:如果卷未连接,则应该成功;如果卷从连接状态开始并且可以成功断开连接,则应该成功。
备选方案¶
保持现状,要求管理员使用后端存储上的API或命令进行手动更改,以保持状态同步。Nova没有API来清理BlockDeviceMapping表。使用‘reset-state’可以工作,如用例1和用例3所示,或者它可能会破坏事物并使卷无法连接,如用例2和用例4所示。
数据模型影响¶
无
REST API 影响¶
无
安全影响¶
无
通知影响¶
断开连接通知将指示force_detach
其他最终用户影响¶
无
性能影响¶
无
其他部署者影响¶
无
开发人员影响¶
BaseVD类将像今天一样实现force_detach,调用terminate_connection和detach。驱动程序开发者可以覆盖此函数,如果他们希望在驱动程序中执行更多操作。
实现¶
负责人¶
主要负责人:scott-dangelo
工作项¶
对核心Cinder代码的更改 驱动程序实现force_detach(如果希望覆盖cinderclient更改 https://review.openstack.org/#/c/187305/)
依赖项¶
无 Nova更改与本规范无关
测试¶
将根据需要修改test_force_detach*的单元测试。将添加Tempest测试,以验证处于连接或断开状态的卷可以force_detached,然后成功重新连接。
文档影响¶
需要更新python-novaclient更改的文档。
参考资料¶
[2] https://etherpad.openstack.org/p/cinder-meetup-winter-2015 L#405