nova的 microversion 实现
之前想写nova的policy的实现, 但是发现网上,有人写的很不错了。
但是个人认为存在一些问题。 ref: http://www.cnblogs.com/shaohef/p/4527436.html
希望 microversion 还没有人写。
microversion实现
microversion实现的机制,就是在http的头部增加一个请求的小版本, nova的serve大家 搜索 new, type, metaclass, 都会介绍。r 根据这个小版本号,做相应的action。
实在是没有什么好介绍了。
这个我想像的microversion有些gap。 我开始以为是在url中指定版本号,而不是在head中。
microversion的值得研究的是如下这段代码。
class subContorller(wsgi.Controller)
@wsgi.Controller.api_version("2.1", "2.3")
def my_api_method(self, req, id):
.... method_1 ... @wsgi.Controller.api_version("2.4") #noqa
def my_api_method(self, req, id):
.... method_2 ...
来自: http://docs.openstack.org/developer/nova/devref/api_microversions.html#changing-a-method-s-behaviour
这段代码,有点诡异,在一个类中实现了两个同名的属性,后面的那个将覆盖前面的那个。
如果是熟悉python的类和实例创建过程的,肯定认为很easy。
瞬间就能想到实现原理, 比如说 不正直的绅士, 他直接做过类似的代码。
其实在IBM的kvm的team,做发行版本的同事,也能想到怎么实现的。
因为我之前给他们介绍个python的类和实例创建过程,其实google/so 一大堆。
我的介绍肯定不如他们自己学习效果好,我纯粹就是显摆而已。
我们要在magnum上,实现microversion,所以我我按照自己的思路尝试自己实现一个。
首先,在同一个类中,定义多个同名函数,最后一个函数, 会覆盖其他的。
怎么办呢?
跟大家一样,第一想法是重载 __getattribute__ 的类。
做法是重名的函数,想办法重新命名。 然后在__getattribute__中,知道期望的函数。
发现,没有找到一个合适的位置,来hack重名的函数。
下面代码中的第5行,是我找到的唯一可能问位置,但是,这个代码只有类的实例才会调用。 ~~~~
def operater(min, max):
def operate(fn):
def wraper(self, *args, **kv):
if fn.func_name not in self.funs:
self.funs[fn.func_name] = [(fn.func_name+"_"+min+"_"+max, wraper)]
else:
self.funs[fn.func_name].append((fn.func_name+"_"+min+"_"+max, wraper))
print getattr(self, fn.func_name)
print "begin decorate"
return fn(self, *args, **kv)
print "end decorate"
type(self)
return wraper
return operate class Controller(object):
funs = {}
def __init__(self):
print self def __getattribute__(self, name):
if name in self.funs:
all_funs = self.funs[name]
fun = self.funs[0][1]
return fun
return object.__getattribute__(self, name) @operater("1.0", "1.5") # noqa
def fun1(self):
print self
print "inline fun1" @operater("1.0", "1.6") # noqa
def fun1(self):
print self
print "inline fun2" if __name__ == '__main__':
print "start main"
import pdb
pdb.set_trace()
i = Controller()
print dir(i)
i.fun1()
大家可以尝试写一下, 不知道有没有实现的可能, 过程中可能会有不少坑。
实在是给大家做过太多的培训了,类合实例的创建过程,还是比较清楚的。
休息了一下,立马清醒。 发现自己比较傻逼,这个位置是创建类的时候。
大家 搜索 new, type, metaclass, 都会介绍。
查看nova的代码,果真如此。
nova采用了six.add_metaclass 来构造类。把nova的相关代码摘取如下, 很简单,都不需要解释。
import six
class VersionedMethod(object):
def __init__(self, name, start_version, end_version, func):
self.name = name
self.start_version = start_version
self.end_version = end_version
self.func = func
def __str__(self):
return ("Version Method %s: min: %s, max: %s"
% (self.name, self.start_version, self.end_version))
VER_METHOD_ATTR = 'versioned_methods'
obj_min_ver = "2.0"
obj_max_ver = "2.3"
class ControllerMetaclass(type):
def __new__(mcs, name, bases, cls_dict):
versioned_methods = None
# start with wsgi actions from base classes
for base in bases:
# actions.update(getattr(base, 'wsgi_actions', {}))
if base.__name__ == "Controller":
# NOTE(cyeoh): This resets the VER_METHOD_ATTR attribute
# between API controller class creations. This allows us
# to use a class decorator on the API methods that doesn't
# require naming explicitly what method is being versioned as
# it can be implicit based on the method decorated. It is a bit
# ugly.
print "+" * 80
print base.__dict__
if VER_METHOD_ATTR in base.__dict__:
versioned_methods = getattr(base, VER_METHOD_ATTR)
delattr(base, VER_METHOD_ATTR)
for key, value in cls_dict.items():
if not callable(value):
continue
if versioned_methods:
cls_dict[VER_METHOD_ATTR] = versioned_methods
return super(ControllerMetaclass, mcs).__new__(mcs, name, bases,
cls_dict)
class abc(object):
pass
@six.add_metaclass(ControllerMetaclass)
class Controller(abc):
def __getattribute__(self, key):
def version_select(*args, **kwargs):
# The first arg to all versioned methods is always the request
# object. The version for the request is attached to the
# request object
func_list = self.versioned_methods[key]
print func_list
for func in func_list:
print "^" * 80
return func.func(self, *args, **kwargs)
# print func.func_name, func.obj_min_ver, func.obj_max_ver
return func.func(self, *args, **kwargs)
# No version match
raise exception.VersionNotFoundForAPIMethod(version=ver)
try:
# super(LockerDecorator, self).__getattribute__(self, name)
version_meth_dict = abc.__getattribute__(self, VER_METHOD_ATTR)
except AttributeError:
# No versioning on this class
return abc.__getattribute__(self, key)
if version_meth_dict and \
key in abc.__getattribute__(self, VER_METHOD_ATTR):
return version_select
return abc.__getattribute__(self, key)
# NOTE(cyeoh): This decorator MUST appear first (the outermost
# decorator) on an API method for it to work correctly
@classmethod
def api_version(cls, min_ver, max_ver=None):
def decorator(f):
# Add to list of versioned methods registered
func_name = f.__name__
new_func = VersionedMethod(func_name, obj_min_ver, obj_max_ver, f)
func_dict = getattr(cls, VER_METHOD_ATTR, {})
if not func_dict:
setattr(cls, VER_METHOD_ATTR, func_dict)
# global func_list
func_list = func_dict.get(func_name, [])
if not func_list:
func_dict[func_name] = func_list
func_list.append(new_func)
func_list.sort(key=lambda f: f.start_version, reverse=True)
return f
return decorator
class MyController(Controller):
@Controller.api_version("2.2")
def create(self, req, body):
print "create v2.2"
@Controller.api_version("2.1", "2.1") # noqa
def create(self, req, body):
print "create v2.1"
def delete(self, req, body):
print "delete no version"
if __name__ == "__main__":
i = MyController()
i.create("", "")
i.delete("", "")
print "exit"
nova的 microversion 实现的更多相关文章
- Nova PhoneGap框架 第一章 前言
Nova PhoneGap Framework诞生于2012年11月,从第一个版本的发布到现在,这个框架经历了多个项目的考验.一直以来我们也持续更新这个框架,使其不断完善.到现在,这个框架已比较稳定了 ...
- Nova PhoneGap框架 总结
Nova PhoneGap Framework 是完全针对PhoneGap应用程序量身定做的,在这个框架下开发的应用程序很容易实现高质量的代码,很容易让程序拥有很好的性能和用户体验. 在经历了多个项目 ...
- nova instance出错:"message": "Proxy error: 502 Read from server failed
执行 $ nova resize instance1 时候出错: {, "details": " File \"/opt/stack/nova/nova/com ...
- Nova PhoneGap框架 第二章 理解index.html
跟绝大多数PhoneGap程序一样,Index.html是程序的入口.这个页面应该完成应用程序的初始化工作. 首先,让我们来看看这个页面通常都长什么样子: 下面我将一一解释这个页面都做了哪些初始化工作 ...
- Nova PhoneGap框架 第三章 页面
页面在项目架构中是一个很重要的概念,它让我们能够将一个功能复杂的项目拆分成一个一个功能比较独立的小区域,这极大的提高了代码的可读性和可维护性. 在我们这个框架中,一个页面由JS和HTML两部分组成,首 ...
- Nova PhoneGap框架 第四章 本地数据库
我一直想把EntityFramework(简称EF)的那一套搬过来,应用于HTML5 SQLite. 幸运的是,我几乎做到了,有些功能无法完成的那是因为SQLite本身不支持.至少从现在已经完成的功能 ...
- Nova PhoneGap框架 第七章 设备事件处理
我们的框架包含了几种设备事件的处理,目的是为了让我们的程序员更容易的完成代码.这些事件包括:回退键(Android)和横竖屏切换事件. 7.1 Android回退键 首先来说说回退键的事件处理.当用户 ...
- Nova PhoneGap框架 第八章 滚动条
你可能会疑惑为什么滚动条这么常见的功能会在这里单独列出,但如果你有过PhoneGap开发经验的话,你就会发现要在Android 2.3 里面实现滚动条那真不是一件容易的事. 8.1 概述 目前主流的P ...
- Nova PhoneGap框架 第九章 控件
我们的框架中也提供了一些常用的控件,这些控件大多都依赖于我们的框架,也正是在我们的框架下才使得实现这些控件的变得更简单.但是我们的框架是不依赖与这些控件的,如果你用不上这些控件,你完全可以把相关的代码 ...
随机推荐
- virtualBox 安装CentOS 全屏
在VirtualBox里安装CentOS系统,会遇到“增强工具”无法正常安装,主要的原因是出在Kernel 库找不到. 错误提示如下: 通过查看日志文件: cat /var/log/vboxadd-i ...
- python基础(四)
内置函数 callable() #判断是否能够被调用执行,可以调用返回True,例如函数和类 chr() #将ascii值转换为字符,例如print(chr(65) )输出为a ord()#将字符转换 ...
- QT5中QString与char *的相互转换
以例子说明: #include <QApplication> #include <QDebug> #include <QString> #include <Q ...
- tornado web框架
tornado web框架 tornado简介 1.tornado概述 Tornado就是我们在 FriendFeed 的 Web 服务器及其常用工具的开源版本.Tornado 和现在的主流 Web ...
- struts2的对象工厂(ObjectFactory)
ObjectFactory,是xwork中很重要的一个类,是产生action的地方.单独使用xwork的时候,action都是这个类创建的.struts2包装了ObjectFactory,自成了一个S ...
- android-Java SoftReference,WeakReference,Direct Reference简介
主要部分: SoftReference(软引用)是java中一个用来实现缓存内容的类.通过此类,可以观察某对象什么时候会被垃圾收集的执行绪清除.被 Soft Reference 指到的对象,即使没有任 ...
- Android开发:自定义GridView/ListView数据源
http://mobile.51cto.com/android-259861.htm 在开发中,我们常常会遇到比较复杂的GridView/ListView的布局,重新实现BaseAdapter不但能帮 ...
- 中国25位最具影响力的IC人物
当今许多企业的领导者几乎已经成为其企业的代名词,而在芯片业,我们听说的更多的是“龙芯”.“国芯”,他们的领导者的声音却鲜有传出.芯片业透出的强烈的民族色彩,也使这些隐身的企业家们的注意力更聚集在研发上 ...
- Windows Azure Service Bus 推动财务服务门户的高可用性和可伸缩性
抵押贷款公司和评估管理公司面临着快速.复杂且数据量极大的业务流程.他们需要可快速.轻松设置且容量几乎无限的可伸缩的企业级服务,来对处理评估订单以及自动化流程本身所产生的所有文档和数据进行管理. 这听起 ...
- 迎接 Windows Azure 和 DNN 挑战,几分钟内快速构建网站!
编辑人员注释:本文章由高级商务策划师兼开发平台推广者 Neeti Gupta 撰写. 曾几何时,构建一个简单的网站需要耗费好几个月的时间.在过去,.NET 开发人员和设计社区的一些成员使用 DNN(以 ...