之前想写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的值得研究的是如下这段代码。
1 class subContorller(wsgi.Controller) 2 @wsgi.Controller.api_version("2.1", "2.3") 3 def my_api_method(self, req, id): 4 .... method_1 ... 5 6 @wsgi.Controller.api_version("2.4") #noqa 7 def my_api_method(self, req, id): 8 .... 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行,是我找到的唯一可能问位置,但是,这个代码只有类的实例才会调用。 ~~~~
1 def operater(min, max): 2 def operate(fn): 3 def wraper(self, *args, **kv): 4 if fn.func_name not in self.funs: 5 self.funs[fn.func_name] = [(fn.func_name+"_"+min+"_"+max, wraper)] 6 else: 7 self.funs[fn.func_name].append((fn.func_name+"_"+min+"_"+max, wraper)) 8 print getattr(self, fn.func_name) 9 print "begin decorate" 10 return fn(self, *args, **kv) 11 print "end decorate" 12 type(self) 13 return wraper 14 return operate 15 16 17 class Controller(object): 18 funs = {} 19 def __init__(self): 20 print self 21 22 def __getattribute__(self, name): 23 if name in self.funs: 24 all_funs = self.funs[name] 25 fun = self.funs[0][1] 26 return fun 27 return object.__getattribute__(self, name) 28 29 @operater("1.0", "1.5") # noqa 30 def fun1(self): 31 print self 32 print "inline fun1" 33 34 @operater("1.0", "1.6") # noqa 35 def fun1(self): 36 print self 37 print "inline fun2" 38 39 if __name__ == '__main__': 40 print "start main" 41 import pdb 42 pdb.set_trace() 43 i = Controller() 44 print dir(i) 45 i.fun1()