一文看懂ovirt的supervdsmd服务
在ovirt的计算节点上supervdsmd.service是有root用户权限的,可以操作系统底层的资源,其他的服务需要与之通讯来完成对资源的操作。
其主要完成两个工作:
动态扩展_SuperVdsm和启动BaseManager(multiprocessing.managers)服务端。
然后就是监听其他服务发送过的API请求并执行。
一.动态扩展_SuperVdsm
关键代码:
if _glusterEnabled:
for name, func in listPublicFunctions(GLUSTER_MGMT_ENABLED):
setattr(_SuperVdsm, name, bind(logDecorator(func)))
上述代码实现的功能是:
把gluster目录下的模块的函数到取出来,在函数名字之前加了字符串gluster,然后赋给_SuperVdsm。
关键代码:
for _, module_name, _ in pkgutil.iter_modules([supervdsm_api.
__path__[0]]):
module = importlib.import_module('%s.%s' %
(supervdsm_api.__name__,
module_name))
api_funcs = [f for _, f in module.__dict__.iteritems()
if callable(f) and getattr(f, 'exposed_api', False)]
for func in api_funcs:
setattr(_SuperVdsm, func.__name__, bind(logDecorator(func)))
上述代码实现的功能是:
把supervdsm_api目录下的模块中被@expose的函数到取出来,直接赋给_SuperVdsm。这样就为给supervdsmd.service添加新的API提供了很简单的方法:只要在supervdsm_api文件夹下新建一个pthon文件就可以自动导出新的API了。
setattr之前的_SuperVdsm:
初始的_SuperVdsm中函数很少,都在class _SuperVdsm中定义,例如mount、multipath_status、removeDeviceMapping等。
setattr之后的_SuperVdsm:
动态扩展之后的_SuperVdsm中函数包含了所有要导出的API函数,包括三部分API:
1.原来_SuperVdsm的API,例如mount、multipath_status、getdeviSCSIinfo等;
2.gluster文件夹下导出的API,例如gluster/cli.py中的snapshotInfo等;
3.supervdsm_api文件夹下导出的API,例如supervdsm_api/hwinfo.py中的getHardwareInfo等。
二.启动BaseManager(multiprocessing.managers)服务端
启动一个BaseManager的serve_forever线程程,它监听/var/run/vdsm/svdsm.sock,它的callable设置为_SuperVdsm供BaseManager的客户端来调用其中的API。(供调用的API在前面已经全部赋给了_SuperVdsm)
关键代码:
manager = _SuperVdsmManager(address=address, authkey='')
manager.register('instance', callable=_SuperVdsm)
server = manager.get_server()
servThread = concurrent.thread(server.serve_forever)
servThread.start()
其中_SuperVdsmManager的定义:
class _SuperVdsmManager(BaseManager):
pass
到此supervdsmd.service的任务就完成了,剩下的就是等着client来调用_SuperVdsm中的API了。
三.client(例如vdsmd.service)如何与supervdsmd.service通信
在common/supervdsm.py中实现了BaseManager(multiprocessing.managers)的clinet: SuperVdsmProxy:
class SuperVdsmProxy(object):
def _connect(self):
self._manager = _SuperVdsmManager(address=ADDRESS, authkey='')
self._manager.register('instance')
self._manager.register('open')
try:
function.retry(
self._manager.connect, Exception, timeout=60, tries=3)
在vdsmd.service中使用SuperVdsmProxy来调用supervdsmd.service的API的方法:
from vdsm.common import supervdsm
supervdsm.getProxy().xxxxxxAPI()
也可以自己写一个python文件来调用supervdsmd.service的API
例如:
from vdsm.common import supervdsm
print supervdsm.getProxy().getHardwareInfo()
下面是完整的架构图:
BaseManager例子
为了更好的理解BaseManager的工作过程,我们把vdsm中关于BaseManager(multiprocessing.managers)的服务端和客户端代码单独摘出来,组成一个可运行的domo程序:
服务端:
from multiprocessing.managers import BaseManager
class _SuperVdsmManager(BaseManager):
pass
class _SuperVdsm(object):
def test_api(*args, **kwargs):
return "this is server"
def start_server():
manager = _SuperVdsmManager(address='/tmp/test.sock', authkey='')
manager.register('instance', callable=_SuperVdsm)
server = manager.get_server()
server.serve_forever()
start_server()
客户端:
class ProxyCaller(object):
def __init__(self, supervdsmProxy, funcName):
self._funcName = funcName
self._supervdsmProxy = supervdsmProxy
def __call__(self, *args, **kwargs):
callMethod = lambda:
getattr(self._supervdsmProxy._svdsm, self._funcName)(*args,
**kwargs)
return callMethod()
class SuperVdsmProxy(object):
def __init__(self):
self._manager = None
self._svdsm = None
self._connect()
def open(self, *args, **kwargs):
return self._manager.open(*args, **kwargs)
def _connect(self):
self._manager = _SuperVdsmManager(address='/tmp/test.sock', authkey='')
self._manager.register('instance')
self._manager.register('open')
self._manager.connect()
self._svdsm = self._manager.instance()
def __getattr__(self, name):
return ProxyCaller(self, name)
def start_client():
instance = SuperVdsmProxy()
print instance.test_api()
start_client()
关注本公众号,了解更多关于云计算虚拟化的知识。
- VS 2010 SP1的一个功能(添加可部署依赖项)
- 一组扁平化组件推荐下载(PSD 格式)
- [C#6] 6-表达式形式的成员函数
- 在启用了IPV6的机器上获取客户端ipv4地址
- 使用 MDT 2010 进行可伸缩部署
- 性能优化工具 MVC Mini Profiler
- 在ASP.NET应用启动的时候初始化的几种方法
- [C#6] 8-异常增强
- 信息超新星的诞生
- jquery mobile 移动web(2)
- [腾讯社区开放平台].NET SDK基于New BSD协议开源
- IIS7.5上的REST服务的Put操作发生HTTP Error 405.0 - Method Not Allowed 解决方法
- 使用 asp.net mvc和 jQuery UI 控件包
- jquery mobile 移动web(1)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 35.Python字符串格式运算符%
- 好一个 Spring Boot 开源在线考试系统!解决了我的燃眉之急
- OC基础--数据类型与表达式
- OC基础--字符串
- 编写优雅的 commit message 并自动生成 changelog
- RL实践2——RL环境gym搭建
- 【Java面试总结】多线程
- RL实践1——动态规划值迭代
- RL实践3——为Agent添加Policy
- CentOS 快速安装Python3和pip3
- Linux使用 常见经验和技巧总结
- SwiftUI:辅助功能——简单介绍
- Xshell突出显示集
- samba服务安装脚本
- 【Vue.js】Vue.js组件库Element中的树形控件、分页、标记、头像和警告