Nova中的Hook机制
Nova的代码中支持Hook机制,也就是在某些函数的前后,可以加入自己的代码逻辑。Hook代码可以完全独立于Nova开发,本质上使用setuptools的entry points机制。K版本的OpenStack Nova中支持Hook的流程有:
nova.compute .api.API:create
nova.compute.manager.ComputeManager:_do_build_and_run_instance
nova.compute.manager.ComputeManager:_delete_instance
nova.network.base_api:update_instance_cache_with_nw_info
一:Nova中的Hook原理
以nova.compute.api.API: create方法为例,该方法是nova-api收到创建实例的命令之后要调用的方法,具体代码如下:
@hooks.add_hook("create_instance")
def create(self, context, instance_type,
image_href, kernel_id=None, ramdisk_id=None,
min_count=None, max_count=None,
display_name=None, display_description=None,
key_name=None, key_data=None, security_group=None,
availability_zone=None, user_data=None, metadata=None,
injected_files=None, admin_password=None,
block_device_mapping=None, access_ip_v4=None,
access_ip_v6=None, requested_networks=None, config_drive=None,
auto_disk_config=None, scheduler_hints=None, legacy_bdm=True,
shutdown_terminate=False, check_server_group_quota=False):
"""Provision instances, sending instance information to the
scheduler. The scheduler will determine where the instance(s)
go and will handle creating the DB entries.
Returns a tuple of (instances, reservation_id)
"""
...
可见该方法被装饰器hooks.add_hook所修饰了,这就是加载钩子的方法,看一下hooks.add_hook代码:
def add_hook(name, pass_function=False):
"""Execute optional pre and post methods around the decorated
function. This is useful for customization around callables.
""" def outer(f):
f.__hook_name__ = name @functools.wraps(f)
def inner(*args, **kwargs):
manager = _HOOKS.setdefault(name, HookManager(name)) function = None
if pass_function:
function = f manager.run_pre(name, args, kwargs, f=function)
rv = f(*args, **kwargs)
manager.run_post(name, rv, args, kwargs, f=function) return rv return inner
return outer
经过该装饰器的修饰之后,调用create(*args, **kwargs)方法时,实际上就是调用的inner(*args,**kwargs)函数。
inner函数比较简单,首先在全局变量_HOOKS中根据name寻找该方法对应的HookManager。这里的name就是add_hook的入参:"create_instance"。若第一次调用create方法,则创建一个针对该name的HookManager。然后首先调用manager.run_pre,接着是create方法本身,最后调用manager.run_post方法。
这样就相当于在create方法的前后插入了代码。看一下HookManager的实现:
class HookManager(stevedore.hook.HookManager):
def __init__(self, name):
"""Invoke_on_load creates an instance of the Hook class :param name: The name of the hooks to load.
:type name: str
"""
super(HookManager, self).__init__(NS, name, invoke_on_load=True) def _run(self, name, method_type, args, kwargs, func=None):
if method_type not in ('pre', 'post'):
msg = _("Wrong type of hook method. "
"Only 'pre' and 'post' type allowed")
raise ValueError(msg) for e in self.extensions:
obj = e.obj
hook_method = getattr(obj, method_type, None)
if hook_method:
LOG.debug("Running %(name)s %(type)s-hook: %(obj)s",
{'name': name, 'type': method_type, 'obj': obj})
try:
if func:
hook_method(func, *args, **kwargs)
else:
hook_method(*args, **kwargs)
except FatalHookException:
msg = _LE("Fatal Exception running %(name)s "
"%(type)s-hook: %(obj)s")
LOG.exception(msg, {'name': name, 'type': method_type,
'obj': obj})
raise
except Exception:
msg = _LE("Exception running %(name)s "
"%(type)s-hook: %(obj)s")
LOG.exception(msg, {'name': name, 'type': method_type,
'obj': obj}) def run_pre(self, name, args, kwargs, f=None):
"""Execute optional pre methods of loaded hooks. :param name: The name of the loaded hooks.
:param args: Positional arguments which would be transmitted into
all pre methods of loaded hooks.
:param kwargs: Keyword args which would be transmitted into all pre
methods of loaded hooks.
:param f: Target function.
"""
self._run(name=name, method_type='pre', args=args, kwargs=kwargs,
func=f) def run_post(self, name, rv, args, kwargs, f=None):
"""Execute optional post methods of loaded hooks. :param name: The name of the loaded hooks.
:param rv: Return values of target method call.
:param args: Positional arguments which would be transmitted into
all post methods of loaded hooks.
:param kwargs: Keyword args which would be transmitted into all post
methods of loaded hooks.
:param f: Target function.
"""
self._run(name=name, method_type='post', args=(rv,) + args,
kwargs=kwargs, func=f)
HookManager继承自stevedore.hook.HookManager。该父类就是stevedore用来管理hook类插件的基本类,关于stevedore可以参考《stevedore简介》。实例化HookManager时,传入的插件的namespace是NS =”nova.hooks”, 插件名是name="create_instance"。
HookManager.run_pre和HookManager.run_post方法都是调用的HookManager._run方法,只不过参数method_type分别是”pre”和”post”。
在HookManager._run方法中,轮训找到的插件实例,然后根据method_type寻找对应的实例属性。这样,只要插件类实现了pre和post方法,这里就可以调用这些方法。调用Hook方法时,传入的参数就是调用create方法的参数,还可以加入一个函数参数,这里忽略。
二:创建注册Hook
下面看一下如何创建并注册一个Hook。按照上面的梳理,只要定义一个实现了pre和post方法的类,然后在setup.py中,使用”nova.hooks”作为entry points组名,以” create_instance”为entry point名注册该类即可。下面是类实现:
class SimpleHookCreate (object):
def pre(self, *args, **kwargs):
logger.error("[PRE]this is hook1") def post(self, *args, **kwargs):
logger.error("[POST]this is hook1")
这里pre和post方法,只是在日志中打印简单语句而已。下面是该模块的setup.py脚本:
import setuptools setuptools.setup(
name="demo_nova_hooks",
packages=['demo_nova_hooks'],
entry_points={
'nova.hooks': [
'create_instance=demo_nova_hooks.simple:SimpleHookCreate'
]
},
)
有关setuptools、entry point的相关知识,参阅《Distutils发布Python模块》、《setuptools简介》等相关文章。
该Hook模块的源码树如下:
setup.py
demo_nova_hooks\
__init__.py
simple.py
使用 python setup.py install命令安装该Hook后,这样在Openstack中创建实例的时候,就会在日志中打印出相应的信息。
另外,因为使用的是stevedore中的Hook方式加载的插件,因此针对同一个entry point组名下的同一个entry point名,可以安装注册多个Hook类。
参考:
http://blog.oddbit.com/2014/09/27/integrating-custom-code-with-n/
http://blog.csdn.net/gqtcgq/article/details/49255995
http://blog.csdn.net/gqtcgq/article/details/49519685
http://blog.csdn.net/gqtcgq/article/details/49620279
Nova中的Hook机制的更多相关文章
- 【repost】JS中的hook机制
hook机制也就是钩子机制,由表驱动实现,常用来处理多种特殊情况的处理.我们预定义了一些钩子,在常用的代码逻辑中去适配一些特殊的事件,这样可以让我们少些很多if else语句.举个高考加分的例子,比如 ...
- [转] js中的钩子机制(hook)
什么是钩子机制?使用钩子机制有什么好处? 钩子机制也叫hook机制,或者你可以把它理解成一种匹配机制,就是我们在代码中设置一些钩子,然后程序执行时自动去匹配这些钩子:这样做的好处就是提高了程序的执行效 ...
- Hook机制里登场的角色
稍有接触过 WordPress 主题或插件制作修改的朋友,对 WordPress 的Hook机制应该不陌生,但通常刚接触WordPress Hook 的新手,对其运作原理可能会有点混乱或模糊.本文针对 ...
- 黄聪:WordPress 的 Hook 机制与原理(add_action、add_filter)
稍有接触过 WordPress 主题或插件制作修改的朋友,对 WordPress 的Hook机制应该不陌生,但通常刚接触WordPress Hook 的新手,对其运作原理可能会有点混乱或模糊.本文针对 ...
- MFC中的HOOK编程
HOOK,n.钩, 吊钩,通常称钩子. 在计算机中,是Windows消息处理机制的一个平台,应用程序能够在上面设置子程以监视指定窗体的某种消息,并且所监视的窗体能够是其它进程所创建的.当消息到达后,在 ...
- 插件开发之360 DroidPlugin源码分析(二)Hook机制
转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52124397 前言:新插件的开发,可以说是为插件开发者带来了福音,虽然还很多坑要填补, ...
- PHP中的插件机制原理和实例
PHP项目中很多用到插件的地方,更尤其是基础程序写成之后很多功能由第三方完善开发的时候,更能用到插件机制,现在说一下插件的实现.特点是无论你是否激活,都不影响主程序的运行,即使是删除也不会影响. 从一 ...
- PostgreSQL的hook机制初步学习
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页 本文的目的一是为了备忘,二是为了抛砖引玉,希望 ...
- 浅谈svn的hook机制
一.什么是钩子 所谓svn的hook机制,就是用户在管理数据仓库的时候,当特定的事件发生时,相应的hook会被调用,hook 其实就相当于特定事件的处理函数. 当前 Subversion 提供了5种可 ...
随机推荐
- C++怎么读入非文本文件中的内容
C++怎么读入非文本文件中的内容 3条回答 #include <io.h> #include <windows.h> void main() { char* pFileName ...
- 多机MySQL一主双从详细安装主从复制
多机MySQL一主双从详细安装 一.复制的工作原理 要想实现AB复制,那么前提是master上必须要开启二进制日志 1.首先master将数据更新记录到二进制日志文件 2.从slave start开始 ...
- 从页面获取form表单提交的数据
1 使用HttpServletRequest,方便灵活 页面代码,使用action提交一个表单,里边有球的id,球的主人,球的颜色,所在省份,区域 <form action="ball ...
- Git同账号多平台配置
最近工作中使用到了Git,虽然以前学习过,但是已经忘的差不多了,遂将本次配置过程整理成笔记以备忘 生成公钥 ssh-keygen -t rsa -C "gana10007@163.com&q ...
- 007-使用python统计代码行数,空行以及注释
# 自己写过的程序,统计一下你写过多少行代码.包括空行和注释,但是要分别列出来 1.打开文件方法 1.1 以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符 f ...
- MyBatis小问题-Mapper中错误No constructor found...
前两天又被公司叫去修改其他产品的一些问题了,没有看java相关的,今天周六,看了看MyBatis东西. 就是简单的在MySql中建了个users表,很简单,包含id,name,age,写了个bean. ...
- mysql8忘记密码的解决方法
mysql8忘记密码的解决方法 1.管理员身份打开cmd,进入dos 2.停止mysql服务 命令:net stop mysql 3.无密码启动 命令:mysqld --console --skip- ...
- Android的ADB学习笔记
1.ADB的常用命令 Pull命令:adb -e|-d pull {文件的路径} {获取文件路径} 2. 文件操作的基本命令 ls -al:显示当下目录下用户对文件的操作权限. = la -al ...
- QT应用qmake添加应用图标
总体解决方案: 1.搜索 [Setting the Application Icon]帮助 2.http://doc.qt.io/qt-5/appicon.html 3.可以在主pro文件中加入如下语 ...
- 蚁群算法MATLAB解TSP问题
Excel表exp12_3_1.xls中数据为: clc clear all [xdata,textdata]=xlsread('exp12_3_1.xls'); %加载20个城市的数据,数据按照表格 ...