在卷驱动程序中引入抽象接口模型¶
https://blueprints.launchpad.net/cinder/+spec/abc-volume-drivers
与其使用松散的卷驱动程序接口定义,不如使用 ABC python 库构建抽象类,强制驱动程序实现所需的功能。目标是在运行时避免使用异常,并尽早发现错误,如果驱动程序没有使用正确的接口。
问题描述¶
在 cinder.volume.driver 中定义的卷接口相当宽松。驱动程序可以决定是否实现某种功能。从外部(管理器层)无法看到驱动程序实现了哪些功能。因此,发现它的唯一方法是尝试调用某个功能集的函数,并查看是否引发 NotImplementedError 异常。
用例¶
提议的变更¶
构建一个基础 VolumeDriver 类和子类,这些子类描述了功能集,例如
+-------------------------+
+----------------+ BaseVolumeDriver +---------------+
| | {abstract} | |
| +-----------^-------------+ |
| | |
| | |
+-------+-------------+ +-----------+-------------+ +------------+---------+
| VolumeDriverBackup | | VolumeDriverSnapshot | | VolumeDriverImport |
| {abstract} | | {abstract} | | {abstract} |
+---------------------+ +-------------------------+ +----------------------+
如果驱动程序实现了备份功能并支持卷导入,则应从像这样的接口类继承:
class FooDriver(VolumeDriverBackup, VolumeDriverImport):
...
管理层可以使用 isinstanceof() 来观察给定驱动程序的功能集。
volume_driver = FooDriver(..)
if isinstanceof(volume_driver, VolumeDriverBackup):
pass
使用 python ABC 是首选,因为它具有多种优势(参见 [1],[2])。它将在实例化级别引发 TypeError 异常。其他 OpenStack 项目已经在使用这个库(参见 [3])。
驱动程序迁移¶
与其一步到位地更改所有驱动程序,不如逐步迁移。为此,VolumeDriver 类可以使用与之前相同的接口,并使用 NotImplementedError 异常。这样,所有现有驱动程序都可以逐步迁移到新的概念。
备选方案¶
仅实现子类,不要使用
ABC
数据模型影响¶
无。
REST API 影响¶
无。
安全影响¶
无。
通知影响¶
无。
其他最终用户影响¶
无。
性能影响¶
由于 ABCMeta 及其功能仅在相关数据路径中受到非常有限的使用,因此预计不会产生严重的性能影响。以下常规对象函数可能比以前性能稍差(参见 [5])
- __new__()
- __subclasscheck__(), issubclass()
- __instancecheck__(), isinstance()
性能取决于所使用的类层次结构的深度。所提出的概念在这方面非常简单(最多 2 层)。通常,它是引发/捕获异常的周期与在 for loop 中迭代所有抽象类之间的比较。
其他部署者影响¶
无。
开发人员影响¶
此更改将略微更改所有已实现的驱动程序。功能本身不应更改,但所有驱动程序都需要采用新的类模型。
实现¶
负责人¶
- 主要负责人
Marc Koderer (m-koderer)
- 其他贡献者
Danny Al-Gaaf (danny-al-gaaf)
工作项¶
将在 etherpad 中跟踪。
依赖项¶
无。
测试¶
单元测试需要进行大规模调整,因为到处都在捕获 NotImplementedError 异常。
文档影响¶
无。
参考资料¶
[1]: http://legacy.python.org/dev/peps/pep-3119/ [2]: http://dbader.org/blog/abstract-base-classes-in-python [3]: http://lists.openstack.org/pipermail/openstack-dev/2013-August/014089.html [4]: https://bugs.launchpad.net/tempest/+bug/1346797 [5]: https://hg.python.org/cpython/file/2.7/Lib/abc.py