ironic objects

来源:互联网 发布:淘宝美工要会哪些软件 编辑:程序博客网 时间:2024/05/17 09:20

ironic 的数据类型在ironic/objects包中,应该说是数据模型更合适,node,port,chassis,conductor,事实上,在hardware这一块上数据模型非常多, 大粒度上可以这么分,

然而很多模块不好归类,比如电源,内存,磁盘,风扇,扩展卡等等,我本来认为把这些模型加到node中去而不定义新的模型,这样node将会非常臃肿也不适合做数据的抽象,

期待ironic的改进。


数据模型定义了属性和一些方法(Port会在controller之后直接操作数据库,nodes会在controller中通过rpc到manager中去做一些东西,然后会通过nodes操作数据库)

controller中的module和数据模型一一对应,非常明确, 直接来看数据模型的父类ironic.objects.base.py中的IronicObject,,该类通过@six.add_metaclass(IronicObjectMetaclass) 添加了metaclass, 有一篇讲解metaclass的文章非常好,很经典

http://blog.jobbole.com/21351/

不仅是metaclass,也可以对python本身有更深的了解, 有几句话说的很好“在Python中,类也是对象,你可以动态的创建类。这就是当你使用关键字class时Python在幕后做的事情,而这就是通过元类来实现的”, “type就是Python在背后用来创建所有类的元类”, “Python中所有的东西,注意,我是指所有的东西——都是对象。这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来”,“元类就是创建类这种对象的东西”

type是python内建的元类,用来创建python中的类,我们也可以创建自己的元类,"Python会在类的定义中寻找__metaclass__属性,如果找到了,Python就会用它来创建类,如果没有找到,就会用内建的type来创建这个类",元类的作用就是拦截类的创建,修改类并返回修改后的类。

了解了元类之后来揣测一下IronicObjectMetaClass发挥了怎样的作用:

IronicObject的子类,例如Port,Node等创建的时候:

    def __init__(cls, names, bases, dict_):
        if not hasattr(cls, '_obj_classes'):
            # This will be set in the 'IronicObject' class.
            cls._obj_classes = collections.defaultdict(list)
        else:
            # Add the subclass to IronicObject._obj_classes
            make_class_properties(cls)
            cls._obj_classes[cls.obj_name()].append(cls)

在make_class_properties方法中,

def make_class_properties(cls):
    # NOTE(danms/comstud): Inherit fields from super classes.
    # mro() returns the current class first and returns 'object' last, so
    # those can be skipped.  Also be careful to not overwrite any fields
    # that already exist.  And make sure each cls has its own copy of
    # fields and that it is not sharing the dict with a super class.
    cls.fields = dict(cls.fields)      #拿到子类的fields,例如Port的id,uuid等等
    for supercls in cls.mro()[1:-1]:  #遍历父类
        if not hasattr(supercls, 'fields'):
            continue
        for name, field in supercls.fields.items():
            if name not in cls.fields:   #IronicObject也包含有fields,将父类fields中的created_at, updated_at加入子类的fields
                cls.fields[name] = field
    for name, typefn in cls.fields.iteritems():

        def getter(self, name=name):
            attrname = get_attrname(name)
            if not hasattr(self, attrname):
                self.obj_load_attr(name)  #报错, raise exception
            return getattr(self, attrname)

        def setter(self, value, name=name, typefn=typefn):
            self._changed_fields.add(name)  #记录被改变的attribute
            try:
                return setattr(self, get_attrname(name), typefn(value))
            except Exception:
                attr = "%s.%s" % (self.obj_name(), name)
                LOG.exception(_LE('Error setting %(attr)s'),
                              {'attr': attr})
                raise

        setattr(cls, name, property(getter, setter))   #给fields中的属性设置getter和setter方法,便于读取


IronicObjectSerializer 则在ironic中负责序列化和反序列化工作:

def serialize_entity(self, context, entity):
        if isinstance(entity, (tuple, list, set)):   #如果是普通的元组,list或者set就返回数据类型的实例,int就返回int(x)
            entity = self._process_iterable(context, self.serialize_entity,
                                            entity)
        elif (hasattr(entity, 'obj_to_primitive') and   #是IronicObject就调用IronicObject调用obj_to_promitive()方法
                callable(entity.obj_to_primitive)):
            entity = entity.obj_to_primitive()
        return entity

    def deserialize_entity(self, context, entity):
        if isinstance(entity, dict) and 'ironic_object.name' in entity:
            entity = IronicObject.obj_from_primitive(entity, context=context)
        elif isinstance(entity, (tuple, list, set)):
            entity = self._process_iterable(context, self.deserialize_entity,
                                            entity)
        return entity


remotable_classmethod和remotable两个方法目前在ironic中貌似没有使用,可能我没追出来还。。。



0 0
原创粉丝点击