OpenStack基础之stevedore
来源:互联网 发布:程序员一般工资多少 编辑:程序博客网 时间:2024/05/22 08:29
利用python语言的特性,运行时动态载入代码变得更加容易.很多python应用程序利用这样的特性在运行时发现和载入所谓的"插件",使得自己更易于扩展.python库stevedore就是在Setuptools的entry points基础上,构造了一层抽象层,使开发者可以更容易地在运行时发现和载入插件.
stevedore的代码库在https://github.com/openstack/stevedore,项目主页在https://launchpad.net/python-stevedore,参考文档在http://stevedore.readthedocs.org/.
entry points的每一个命名空间里,可以包含多个entry point项.stevedore要求每一项都符合如下格式:
name = module:importable
左边是插件的名称,右边是它的具体实现,中间用等号分隔开.插件的具体实现用"模块:可导入的对象"的形式来指定,以Ceilometer为例:
ceilometer.compute.virt = libvirt = ceilometer.compute.virt.libvirt.inspector:LibvirtInspector hyperv = ceilometer.compute.virt.hyperv.inspector:HyperVInspector vsphere = ceilometer.compute.virt.vmware.inspector:VsphereInspectorceilometer.hardware.inspectors = snmp = ceilometer.hardware.inspectors.snmp:SNMPInspector
示例中显示了两个不同的entry points的命名空间,“ceilometer.compute.virt"和"ceilometer.hardware.inspectors",分别注册有3个和1个插件.每个插件都符合"名字=模块:可导入对象”的格式,在“ceilometer.compute.virt"命名空间里的libvirt插件,它的具体可载入的实现是ceilometer.compute.virt.libvirt.inspector模块中的LibvirtInspector类.
根据每个插件在entry point中名字和具体实现的数量之间的对应关系不同,stevedore提供了多种不同的类来帮助开发者发现和载入插件,如下图所示:
插件名字: 具体实现建议选用stevedore中的类1: 1stevedore.driver.DriverManager1: nstevedore.hook.HookManagern: mstevedore.extension.ExtensionManager使用stevedore来帮助程序动态载入插件的过程主要分为三个部分:插件的实现,插件的注册,以及插件的载入.下面我们以Ceilometer里动态载入compute agent上的inspector驱动为例来分别进行介绍.
- 插件的实现
Ceilometer的inspector驱动,为从不同类型hypervisor中获取相关数据提供统一的接口以供compute agent调用.下面是它的基类:
#ceilometer/compute/virt/inspector.py
class Inspector(object): def inspect_instances(self): """List the instances on the current host.""" raise NotImplementedError() def inspect_cpus(self, instance_name): """Inspect the CPU statistics for an instance. :param instance_name: the name of the target instance :return: the number of CPUs and cumulative CPU time """ raise NotImplementedError() ...
ceilometer/compute/virt/libvirt/inspector.py,ceilometer/compute/virt/hyperv/inspector.py和ceilometer/compute/virt/vmware/inspector.py分别为kvm,hyperv和vsphere三种不同hypervisor的具体实现,比如:
class LibvirtInspector(virt_inspector.Inspector): def __init__(self, conf): super(LibvirtInspector, self).__init__(conf) self._connection = None @property def connection(self): if not self._connection: self._connection = libvirt_utils.get_libvirt_connection(self.conf) return self._connection @libvirt_utils.retry_on_disconnect def _lookup_by_uuid(self, instance): instance_name = util.instance_name(instance) try: return self.connection.lookupByUUIDString(instance.id) except Exception as ex: if not libvirt or not isinstance(ex, libvirt.libvirtError): raise virt_inspector.InspectorException(six.text_type(ex)) error_code = ex.get_error_code() if (error_code in (libvirt.VIR_ERR_SYSTEM_ERROR, libvirt.VIR_ERR_INTERNAL_ERROR) and ex.get_error_domain() in (libvirt.VIR_FROM_REMOTE, libvirt.VIR_FROM_RPC)): raise msg = _("Error from libvirt while looking up instance " "<name=%(name)s, id=%(id)s>: " "[Error Code %(error_code)s] " "%(ex)s") % {'name': instance_name, 'id': instance.id, 'error_code': error_code, 'ex': ex} raise virt_inspector.InstanceNotFoundException(msg) def inspect_cpus(self, instance): domain = self._get_domain_not_shut_off_or_raise(instance) # TODO(gordc): this can probably be cached since it can be used to get # all data related stats = self.connection.domainListGetStats([domain]) dom_stat = stats[0][1] return virt_inspector.CPUStats(number=dom_stat['vcpu.current'], time=dom_stat['cpu.time'])
- 插件的注册
#setup.cfg
ceilometer.compute.virt = libvirt = ceilometer.compute.virt.libvirt.inspector:LibvirtInspector hyperv = ceilometer.compute.virt.hyperv.inspector:HyperVInspector vsphere = ceilometer.compute.virt.vmware.inspector:VsphereInspector xenapi = ceilometer.compute.virt.xenapi.inspector:XenapiInspector这三个插件注册在命名空间"ceilometer.compute.virt"下,分别叫做libvirt,hyper和vsphere.
- 插件的载入
#ceilometer/compute/virt/libvirt/inspector.py
def get_hypervisor_inspector(conf): try: namespace = 'ceilometer.compute.virt' mgr = driver.DriverManager(namespace, conf.hypervisor_inspector, invoke_on_load=True, invoke_args=(conf, )) return mgr.driver except ImportError as e: LOG.error(_LE("Unable to load the hypervisor inspector: %s") % e) return Inspector(conf)
Ceilometer的compute agent通过调用函数get_hypervisor_inspector来载入具体的某一个插件.此处由于插件和具体实现之间是一对一的关系,所以选用了stevedore和DriverManager类,这个类实例化时可接受的参数如下表所示:参数 = 默认值说 明namespace(字符串类型)命名空间name(字符串类型)插件名invoke_on_load = False(布尔类型)是否调用entry point所返回的插件对象.(在这个例子中,由于entry point所指向的对象是类,相当于是否实例化类对象)invoke_args = {}(元组类型)调用插件对象时所需要的位置参数invoke_kwds = {}(字典类型)调用插件对象时所需要的命名参数on_load_failure_callback = None(函数类型)载入某个entry point失败时的回调函数,参数为(manager,entry point,exception)verify_requirements = False(布尔类型)是否用setup tools来确保此插件的依赖关系都能满足
注意这里我们使用的命名空间"ceilometer.compute.virt"需要和Setuptools中注册的命名空间一致.具体需要载入的插件名称从配置项hypervisor_inspector中读入.
- OpenStack基础之stevedore
- Openstack : 16、Openstack-开发基础 stevedore学习
- OpenStack公共组件oslo之十六——stevedore
- stevedore
- Openstack之Keystone基础
- Openstack之nova基础
- OpenStack基础之Kombu
- openstack基础之eventlet
- openstack基础之--L2,L3
- Openstack基础之oslo(一)
- Openstack基础之oslo.messaging
- stevedore简介
- stevedore简介
- Openstack高可用之基础环境配置
- openstack基础
- OpenStack Nova源码分析之-基础环境配置
- Openstack平台neutron模块之网络基础概念
- openstack基础之python WSGI,paste,Routes,webob
- ERROR:格式化hdfs时出现connection-refused
- poj 3176 Cow Bowling
- POJ 1654 Area
- android_107_ProgressBar旋转
- CCF201609-2 火车购票(100分)
- OpenStack基础之stevedore
- POJ3592 Instantaneous Transference题解
- POJ 2386 Lake Counting (DFS)
- Postgres安装指南-windows10-flask-py3
- MYSQL问题解决方案:Access denied for user 'root'@'localhost' (using password:YES)
- 比大小
- python 数据结构中被忽视的小技巧
- 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。
- Python相关文章索引(3)